树的定义
树是由n(n>=0)个结点组成的有限集合,如果n = 0,成为空树,如果n > 0,则
- 有一个特定的称之为根(root)的结点,它只有直接后继,但没有直接前驱
- 除根以外的其他结点划分为m(m >= 0)个互不相交的有集合T0,T1,…,Tm-1,每个集合又是一棵树,并且称之为根的子树,每棵子树的根节点有且仅有一个直接前驱,但可以有0个或多个直接后继
- 结点的度:一个节点含有的子树的个数成为该结点的度
- 树的度:一棵树中,最大的节点的度称为树的度
- 叶节点或终端节点:度为零的节点
- 非终端节点或分支节点:度不为零的节点
- 父亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的夫节点
- 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点
- 兄弟节点:具有相同父节点的节点称为兄弟节点
- 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推
- 深度:对于任意节点n, n的深度为从根到n的唯一路径长,根的深度为0
- 高度:对于任意节点n, n的高度为从n到一片树叶的最长路径长,所有树叶的高度为0
- 堂兄弟节点:父节点在同一层的节点互为堂兄弟
- 节点的祖先:以某节点为根的子树中任一节点都称为该节点的子树
- 子孙:以某节点为根的子树中任一节点都称为该节点的子孙
- 森林:由m(m>=0)棵互不相交的树集合称为森林
- 树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树,反之是有序树
二叉树的概念
二叉树的定义:
一颗二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵树分别称为左子树和右子树的、互不相交的二叉树组成
二叉树的性质:
- 若二叉树的层次从0开始,则在二叉树的第i层最多由 2i 个结点(i>=0)
- 高度为k的二叉树最多由2k+1-1个结点(k>=-1)
- 对任何一颗二叉树,如果其叶结点个数为n0,度为2的非叶节点个数为n2,则有n0 = n2 + 1;
- 满二叉树:每一个层的结点数都达到最大值,则这个树就是满二叉树
- 完全二叉树:若设二叉树的高度为h,则共有h+1层,除第h层外,其他各层(0~h-1)的结点数都达到最大个数,第h层从右向左连续缺若干结点,这就是完全二叉树
存储表示
- 数据元素之间的关系有两种不同的表示方法:顺序映像和非顺序映像,并由此得到两种不同的存储结构:顺序存储结构和链式存储结构,数据的存储结构是指数据的逻辑结构在计算机中的表示
代码实现
结构定义
typedef char ElemType;
typedef struct BtNode
{
ElemType data;
struct BtNode* leftchild;
struct BtNode* rightchild;
}BtNode, * BinaryTree;
遍历方式
void PreOrder(BtNode* p) //先序遍历
{
if (p != nullptr)
{
cout << p->data << " ";
PreOrder(p->leftchild); //遍历左孩子
PreOrder(p->rightchild); //遍历右孩子
}
}
void InOrder(BtNode* p) //中序遍历
{
if (p != nullptr)
{
InOrder(p->leftchild); //遍历左孩子
cout << p->data << " ";
InOrder(p->rightchild); //遍历右孩子
}
}
void PastOrder(BtNode* p) //后续遍历
{
if (p != nullptr)
{
PastOrder(p->leftchild); //遍历左孩子
PastOrder(p->rightchild); //遍历右孩子
cout << p->data << " ";
}
}
二叉树创建
BtNode* Buynode()
{
BtNode* s = (BtNode*)malloc(sizeof(BtNode));
if (s == nullptr) exit(1);
memset(s, 0, sizeof(BtNode));
return s;
}
BtNode* CBTree1()
{
BtNode* s = nullptr;
ElemType elem;
cin >> elem;
if (elem != '#')
{
s = Buynode();
s->data = elem;
s->leftchild = CBTree1();
s->rightchild = CBTree1();
}
return s;
}
运行验证
int main()
{
BinaryTree root = CBTree1();
PreOrder(root);
cout << endl;
InOrder(root);
cout << endl;
PastOrder(root);
cout << endl;
return 0;
}
- 通过先序遍历,与中序遍历来创建二叉树
int FindIs(const char* is, int n, char ch)
{
int pos = -1;
for (int i = 0; i < n; ++i)
{
if (is[i] == ch)
{
pos = i;
break;
}
}
return pos;
}
BtNode* CreatePI(const char* ps, const char* is, int n)
{
BtNode* s = nullptr;
if (n >= 1)
{
s = Buynode();
s->data = ps[0]; //先序0下标
int pos = FindIs(is, n, ps[0]);
if (pos == -1) exit(1);
s->leftchild = CreatePI(ps + 1, is, pos);
s->rightchild = CreatePI(ps + pos + 1, is + pos + 1, n - pos - 1);
}
return s;
}
BtNode* CreateBinartTreePI(const char* ps, const char* is, int n)
{
if (ps == nullptr || is == nullptr || n <= 0) return NULL;
else return CreatePI(ps, is, n);
}
int main()
{
char ps[] = { "ABCDEFGH" };
char is[] = { "CBEDFAGH" };
char ls[] = { "CEFDBHGA" };
int n = strlen(ps);
BinaryTree root = nullptr;
root = CreateBinartTreePI(ps, is, n);
PreOrder(root);
cout << endl;
InOrder(root);
cout << endl;
PastOrder(root);
cout << endl;
return 0;
}
- 通过中序遍历,与后续遍历创建二叉树
代码与上面基本相似
int FindIs(const char* is, int n, char ch)
{
int pos = -1;
for (int i = 0; i < n; ++i)
{
if (is[i] == ch)
{
pos = i;
break;
}
}
return pos;
}
BtNode* CreateIL(const char* is, const char* ls, int n)
{
BtNode* s = NULL;
if (n > 0)
{
s = Buynode();
s->data = ls[n - 1];
int pos = FindIs(is, n, ls[n - 1]);
if (pos == -1) exit(1);
s->leftchild = CreateIL(is,ls,pos);
s->rightchild = CreateIL(is + pos + 1, ls + pos, n - pos - 1);;
}
return s;
}
BtNode* CreateBinartTreeIL(const char* is, const char* ls, int n)
{
if (is == NULL || ls == NULL || n <= 0) return nullptr;
else return CreateIL(is, ls, n);
}
int main()
{
char ps[] = { "ABCDEFGH" };
char is[] = { "CBEDFAGH" };
char ls[] = { "CEFDBHGA" };
int n = strlen(ps);
BinaryTree root = nullptr;
root = CreateBinartTreeIL(is, ls, n); //中序后续 创建二叉树
PreOrder(root);
cout << endl;
InOrder(root);
cout << endl;
PastOrder(root);
cout << endl;
return 0;
}
非递归实现中序遍历
void NiceInOrder(BtNode* ptr) //非递归中序遍历
{
if(ptr == nullptr) return;
std::stack<BtNode*> st;
while (ptr != nullptr || !st.empty())
{
while (ptr != NULL)
{
st.push(ptr);
ptr = ptr->leftchild;
}
ptr = st.top(); st.pop();
cout << ptr->data;
ptr = ptr->rightchild;
}
cout << endl;
}