一、二叉树相关的概念
树(tree)是n(n>=0)个结点的有限集。n=0时称为空树。在任何一棵非空树中:
(1)有且仅有一个特定的成为根的结点(root);
(2)当n>1时,其余结点可分为m(m<0)个互不相交的有限集T1、T2、……、Tm,其中每一个集合本身又是一棵树,并且称为根的子树,如下图所示:
结点拥有的子树称为结点的度;
度为0的结点称之为叶子节点或终端结点;
树的度是树内各节点度的最大值;
树中结点的最大层次称为树的深度或高度,上图树的深度为4。
二叉树(Binary Tree)是n(n>=0)个结点的有限集合,该集合或者空集(称为空二叉树),或者有一个根结点和两颗互不相交的、分别称为根结点的左子树和右子树的二叉树组成。上图就是一颗二叉树。
二、二叉树的相关代码
(1)二叉树结点定义如下:
typedef char ElemType;
typedef struct BTnode
{
ElemType data; //数据域
BTnode *leftchild; //左孩子指针
BTnode *rightchild; //右孩子指针
}BTnode;
(2)申请一个结点、释放一个结点代码如下:
BTnode *buynode() //申请
{
BTnode *p = (BTnode *)malloc(sizeof(BTnode));
if (p == NULL)
exit(1);
memset(p, 0, sizeof(BTnode *));
return p;
}
void freeNode(BTnode *ptr) //释放
{
free(ptr);
}
(3)创建一颗二叉树的代码如下:
BTnode * create_tree(ElemType *&str) //利用参数创建二叉树
{
BTnode *s = NULL;
if (str!=NULL && *str!=END)
{
s = buynode();
s->data = *str;
s->leftchild = create_tree(++str);
s->rightchild = create_tree(++str);
}
return s;
}
BTnode *create_tree2() //无参数,手动输入创建二叉树
{
BTnode *s = NULL;
ElemType item;
cin >> item;
if (item != END)
{
s = buynode();
s->data = item;
s->leftchild = create_tree2();
s->rightchild = create_tree2();
}
return s;
}
(4)二叉树的三种递归遍历(前序、中序和后序)
void preorder(BTnode *ptr) //前序
{
if (ptr != NULL)
{
cout << ptr->data << " ";
preorder(ptr->leftchild);
preorder(ptr->rightchild);
}
}
void inorder(BTnode *ptr) //中序
{
if (ptr != NULL)
{
inorder(ptr->leftchild);
cout << ptr->data << " ";
inorder(ptr->rightchild);
}
}
void lastorder(BTnode *ptr) //后续
{
if (ptr != NULL)
{
lastorder(ptr->leftchild);
lastorder(ptr->rightchild);
cout << ptr->data << " ";
}
}
(5)二叉树的三种非递归遍历(前序、中序和后序)
void NicePreOrder(BTnode *ptr) //前序
{
if (ptr == NULL) return ;
stack<BTnode *> st;
st.push(ptr);
while (!st.empty())
{
ptr = st.top(); st.pop();
cout << ptr->data << " ";
if (ptr->leftchild != NULL)
{
st.push(ptr->leftchild);
}
if (ptr->rightchild != NULL)
{
st.push(ptr->rightchild);
}
}
cout << endl;
}
void NiceInOrder(BTnode *ptr) //中序
{
if (ptr == NULL) return ;
stack<BTnode *> st;
while (!st.empty() || ptr!=NULL)
{
while (ptr != NULL)
{
st.push(ptr->leftchild);
ptr = ptr->leftchild;
}
ptr = st.top(); st.pop();
cout << ptr->data << " ";
ptr = ptr->rightchild;
}
cout << endl;
}
void NicePastOrder(BTnode *ptr) //后序
{
if (ptr == NULL) return ;
stack<BTnode *> st;
BTnode *tag = NULL;
while (!st.empty() || ptr!=NULL)
{
while (ptr != NULL)
{
st.push(ptr);
ptr = ptr->leftchild;
}
ptr = st.top(); st.pop();
if (ptr->rightchild==NULL || ptr->rightchild==tag)
{
cout << ptr->data << " ";
tag = ptr;
ptr = NULL;
}
else
{
st.push(ptr);
ptr = ptr->rightchild;
}
}
cout << endl;
}
(6)求二叉树的结点个数代码如下:
int size_tree(BTnode *ptr)
{
if (ptr == NULL) return 0;
return size_tree(ptr->leftchild)+size_tree(ptr->rightchild)+1;
}
(7)求二叉树的深度代码如下:
int depth_tree(BTnode *ptr)//二叉树的深度
{
if (ptr == NULL) return 0;
int left = depth_tree(ptr->leftchild);
int right = depth_tree(ptr->rightchild);
return left>right?left+1:right+1;
}
(8)判断是否为满二叉树代码如下:
满二叉树:在一棵二叉树中,如果所有分支节点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。如下图所示:
bool Is_Full_BinaryTree(BTnode *ptr) //数学方法判断
{
int sum = size_tree(ptr);
int depth = depth_tree(ptr);
return (pow(2.0, depth)-1) == sum;
}
bool Is_Full_BinaryTree2(BTnode *ptr) //递归的方法创建
{
return (ptr==NULL)
|| (
ptr!=NULL
&& Is_Full_BinaryTree2(ptr->leftchild)
&& Is_Full_BinaryTree2(ptr->rightchild)
&& depth_tree(ptr->leftchild)==depth_tree(ptr->rightchild)
);
}
(9)打印二叉树的第K层元素,代码如下:
void Print_K_Level_Item(BTnode *ptr, int k)
{
if (ptr==NULL || k<0)
return ;
else if(k == 0)
{
cout << ptr->data << " ";
}
else
{
Print_K_Level_Item(ptr->leftchild, k-1);
Print_K_Level_Item(ptr->rightchild, k-1);
}
}
(10)层次遍历二叉树(递归和非递归),代码如下:
void LevelOrder(BTnode *ptr) //递归
{
if (ptr == NULL) return ;
int level = depth_tree(ptr);
for (int k=0; k<level; k++)
{
Print_K_Level_Item(ptr, k);
}
cout << endl;
}
void NiceLevelOrder(BTnode *ptr)
{
if (ptr == NULL) return ;
queue<BTnode *> qu;
qu.push(ptr);
while (!qu.empty())
{
ptr = qu.front(); qu.pop();
cout << ptr->data << " ";
if (ptr->leftchild != NULL)
{
qu.push(ptr->leftchild);
}
if (ptr->rightchild != NULL)
{
qu.push(ptr->rightchild);
}
}
cout << endl;
}
(11)寻找parent结点,代码如下:
BTnode *Parent(BTnode *ptr, BTnode *child)
{
if (ptr==NULL || ptr->leftchild==NULL || ptr->rightchild==NULL)
return ptr;
else
{
BTnode *p = Parent(ptr->leftchild, child);
if (p == NULL)
{
p = Parent(ptr->rightchild, child);
}
return p;
}
}
BTnode *FindParent(BTnode *ptr,BTnode *child)
{
if (ptr==NULL || child==NULL) return NULL;
else
{
return Parent(ptr, child);
}
}
(12)前序和中序构建二叉树、后序和中序构建二叉树(已知前序和后序不能确定一棵树),代码如下:
int Findls(ElemType *is, int n, ElemType x) //找到X在数组中的位置
{
int pos = -1;
for (int i=0; i<n; ++i)
{
if (is[i] == x)
{
pos = i;
break;
}
}
return pos;
}
BTnode *create_treePI(ElemType *ps, ElemType *is, int n) //前序和中序构建二叉树
{
BTnode *s = NULL;
if (ps!=NULL && is!=NULL && n>0)
{
s = buynode();
s->data = ps[0];
int pos = Findls(is, n, ps[0]);
if(pos == -1) exit(1);
s->leftchild = create_treePI(ps+1, is, pos);
s->rightchild = create_treePI(ps+pos+1, is+pos+1, n-pos-1);
}
return s;
}
BTnode *create_treeIL(ElemType *is, ElemType *ls, int n) //中序和后续构建二叉树
{
BTnode *s = NULL;
if (is!=NULL && ls!=NULL && n>0)
{
s = buynode();
s->data = ls[n-1];
int pos = Findls(is, n, ls[n-1]);
if (pos == -1) exit(1);
s->leftchild = create_treeIL(is, ls, pos);
s->rightchild = create_treeIL(is+pos+1, ls+pos, n-pos-1);
}
return s;
}