二叉树
在计算机科学中,树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为节点)按分支关系组织起来的结构。二叉树(Binary Tree)是每个节点最多有两个子树的有序树。通常子树被称作"左子树"(left subtree)和"右子树"(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。值得注意的是,二叉树不是树的特殊情形。在图论中,二叉树是一个连通的无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根节点的度不大于2。有了根节点后,每个顶点定义了唯一的根节点,和最多2个子节点。然而,没有足够的信息来区分左节点和右节点。
二叉树的存储结构
二叉树常用链式存储。如下图;
最常用的是图a的二叉链表法。
代码实现
下面的代码中我们提供了如下操作:
类定义
#include<iostream>
#include<iomanip>
#include<stack>
#include<queue>
using namespace std;
typedef int ElemType;
//二叉树节点
class BTNode //Binary Tree Node
{
public:
ElemType data;
BTNode* lchild; //左孩子
BTNode* rchild; //右孩子
BTNode(ElemType d, BTNode* left=NULL, BTNode* right=NULL) :data(d), lchild(left), rchild(right){}
};
//二叉树
class BinaryTree
{
private:
//根节点指针
BTNode* Root;
//节点个数
int size;
public:
//构造函数
BinaryTree();
BTNode* buildTree();
//析构函数
~BinaryTree();
//求树的高度
int height();
//获取节点个数
int getSize()
{return size;}
void getHeight(BTNode*, int, int&);
//指定遍历方式
void traverse();
//前序遍历
void preOrder();
void preorder(BTNode*);
//中序遍历
void inOrder();
void inorder(BTNode*);
//后序遍历
void postOrder();
void postorder(BTNode*);
//层次遍历
void levelOrder();
//判断树是否为空
bool empty()
{return Root == NULL;}
//获取根节点
BTNode* root()
{return Root;}
//查找指定节点
bool find(ElemType);
//获取父节点
BTNode* parent(ElemType);
//获取左孩子
BTNode* lchild(ElemType);
//获取右孩子
BTNode* rchild(ElemType);
};类实现
//构造函数
BinaryTree::BinaryTree()
{
size = 0;
cout << "输入根节点 ";
Root = buildTree();
}
BTNode* BinaryTree::buildTree()
{
ElemType data;
BTNode* p = NULL;
cin >> data;
//输入0结束
if (data == 0)
return p;
else
{
p = new BTNode(data);
size++;
if (!p)
{
cerr << "内存分配失败!" << endl;
exit(0);
}
else
{
cout << "请输入 " << data << " 节点的左孩子 ";
p->lchild = buildTree();
cout << "请输入 " << data << " 节点的右孩子 ";
p->rchild = buildTree();
}
}
return p;
}
//析构函数
BinaryTree::~BinaryTree()
{
queue<BTNode*> q;
q.push(Root);
BTNode* p = NULL;
while (!q.empty())
{
p = q.front();
q.pop();
//左孩子不为空,则左孩子入队
if (p->lchild)
q.push(p->lchild);
//右孩子不为空,则右孩子入队
if (p->rchild)
q.push(p->rchild);
//释放内存
delete p;
}
}
//求树的高度
int BinaryTree::height()
{
if (empty())
return 0;
int h = 0;
getHeight(Root, 0, h);
return h;
}
void BinaryTree::getHeight(BTNode* p, int level, int &h)
{
if (p)
{
if (level > h)
h = level;
getHeight(p->lchild, level + 1, h);
getHeight(p->rchild, level + 1, h);
}
}
//指定遍历方式
void BinaryTree::traverse()
{
int choice;
cout << "输入遍历方式:0(前序)、1(中序)、2(后序)、3(层次):";
cin >> choice;
while (choice < 0 || choice > 3)
{
cout << "输的不对!请重新输入: ";
cin >> choice;
}
switch(choice)
{
case 0:preOrder(); break;
case 1:inOrder(); break;
case 2:postOrder();break;
case 3:levelOrder(); break;
}
}
//前序遍历:根->左->右
void BinaryTree::preOrder()
{
BTNode* pnode = Root;
preorder(pnode);
cout << endl;
}
void BinaryTree::preorder(BTNode* p)
{
if (p)
{
cout << setw(4) << p->data;
preorder(p->lchild);
preorder(p->rchild);
}
}
//中序遍历:左->根->右
void BinaryTree::inOrder()
{
BTNode* pnode = Root;
inorder(pnode);
cout << endl;
}
void BinaryTree::inorder(BTNode* p)
{
if (p)
{
inorder(p->lchild);
cout << setw(4) << p->data;
inorder(p->rchild);
}
}
//后序遍历:左->右->根
void BinaryTree::postOrder()
{
BTNode* pnode = Root;
postorder(pnode);
cout << endl;
}
void BinaryTree::postorder(BTNode* p)
{
if (p)
{
postorder(p->lchild);
postorder(p->rchild);
cout << setw(4) << p->data;
}
}
//层次遍历
void BinaryTree::levelOrder()
{
//使用STL中的队列
queue<BTNode*> q;
//根节点入队
q.push(Root);
BTNode* p = NULL;
while (!q.empty())
{
p = q.front();
//打印
cout << setw(4) << p->data;
q.pop();
//左孩子不为空,则左孩子入队
if (p->lchild)
q.push(p->lchild);
//右孩子不为空,则右孩子入队
if (p->rchild)
q.push(p->rchild);
}
cout << endl;
}
//查找指定节点
bool BinaryTree::find(ElemType data)
{
if (!empty())
{
//按层次遍历查找
queue<BTNode*> q;
q.push(Root);
BTNode* p = NULL;
while (!q.empty())
{
p = q.front();
//比较
if(p->data==data)
return true;
q.pop();
if (p->lchild)
q.push(p->lchild);
if (p->rchild)
q.push(p->rchild);
}
}
//在树空和不存在该节点的情况下,都返回false
return false;
}
//获取父节点
BTNode* BinaryTree::parent(ElemType data)
{
if (!empty())
{
//根节点的父节点为空
if (Root->data == data)
return NULL;
stack<BTNode*> s;
BTNode* p = Root;
while (!s.empty() || p)
{
if (p)
{
if ((p->lchild && p->lchild->data == data) || (p->rchild && p->rchild->data == data))
return p;
s.push(p);
p = p->lchild;
}
else
{//左子树访问完后,访问右子树
p = s.top();
s.pop();
p = p->rchild;
}
}
}
return NULL;
}
//获取左孩子
BTNode* BinaryTree::lchild(ElemType data)
{
if (!empty())
{
//按层次遍历查找
queue<BTNode*> q;
q.push(Root);
BTNode* p = NULL;
while (!q.empty())
{
p = q.front();
//比较
if (p->data == data)
return p->lchild;
q.pop();
if (p->lchild)
q.push(p->lchild);
if (p->rchild)
q.push(p->rchild);
}
}
//在树空和不存在该节点的情况下,都返回NULL
return NULL;
}
//获取右孩子
BTNode* BinaryTree::rchild(ElemType data)
{
if (!empty())
{
//按层次遍历查找
queue<BTNode*> q;
q.push(Root);
BTNode* p = NULL;
while (!q.empty())
{
p = q.front();
//比较
if (p->data == data)
return p->rchild;
q.pop();
if (p->lchild)
q.push(p->lchild);
if (p->rchild)
q.push(p->rchild);
}
}
//在树空和不存在该节点的情况下,都返回NULL
return NULL;
}
int main()
{
cout << "******二叉树******" << endl;
BinaryTree tree;
cout << "树的高度是 " << tree.height() << endl;
cout << "树中共有节点个数 " << tree.getSize() << endl;
tree.traverse();
ElemType data = 2;
cout << "对节点 " << data << " 进行查询" << endl;
cout << "存在于树中吗?";
tree.find(data) ? cout << "Yes!" <<endl: cout << "No!" << endl;
BTNode* p = NULL;
p = tree.parent(data);
p ? cout << "父节点是 " << p->data << endl : cout << data << "是根节点,故并无父节点" << endl;
p = tree.lchild(data);
p ? cout << "左孩子是 " << p->data << endl : cout << "无左孩子!" << endl;
p = tree.rchild(data);
p ? cout << "右孩子是 " << p->data << endl : cout << "无右孩子!" << endl;
system("pause");
return 0;
}
遍历算法的非递归实现
//前序遍历非递归算法
void BinaryTree::preOrderWithoutRecursion()
{
if (!empty())
{
stack<BTNode*> s;
BTNode* p = Root;
s.push(p);
while (!s.empty())
{
cout << setw(4) << p->data;
if (p->rchild)
s.push(p->rchild);
if (p->lchild)
p = p->lchild;
else
{//左子树访问完了,访问右子树
p = s.top();
s.pop();
}
}
cout << endl;
}
}//中序遍历的非递归实现
void BinaryTree::inOrderWithoutRecursion()
{
if (!empty())
{
stack<BTNode*> s;
BTNode* p = Root;
while (!s.empty() || p)
{
if (p)
{//一直下降到最左边
s.push(p);
p = p->lchild;
}
else
{
p = s.top();
s.pop();
cout << setw(4) << p->data;
p = p->rchild;
}
}
cout << endl;
}
}完整代码下载:二叉树
转载请注明出处:http://blog.csdn.net/zhangxiangdavaid/article/details/36634411
若有所帮助,顶一个哦!
专栏目录:数据结构与算法目录
原文:http://blog.csdn.net/zhangxiangdavaid/article/details/36634411