一.树的定义与性质
1.空树:没有结点的树;
2.树的层次:根结点为第一层,根节点子树的根节点为第二层;
3.度:结点子树的棵树,叶结点度为0;
4.有 n 个结点的树,边数为 n - 1;
5.结点的深度:从根结点(深度为1)开始,自顶向下;
结点的高度:从叶结点(高度为1)开始,自底向上;
二.二叉树的递归定义
1.第一种情况:二叉树是空树;第二种情况:二叉树由根节点、左子树、右子树构成;
2.二叉树与度为2的树:二叉树不能随意交换左右两棵子树的位置,树的结点的子树是不区分左右顺序的;
3.满二叉树:每一层的结点数都达到最大;
完全二叉树:除了最下面一层,其余层的结点数都达到了最大,最下面一层只从左到右连续存在若干结点,右边的结点都不存在;
三.二叉树的存储结构与基本操作
1.二叉树的存储结构(利用链表来定义):
struct node {
typename data;
node* lchild;
node* rchild;
};
新建结点的函数:
node* newNode(int v) {
node* Node = new node;
Node->data = v;
Node->lchild = Node->rchild = NULL;
return Node; //返回新建结点的地址
}
2.二叉树结点的查找和修改:
void search(node* root, int x, int newdata) {
if(root == NULL) return;
if(root->data == x) root->data = newdata;
search(root->lchild, x, newdata);
search(root->rchild, x, newdata);
}
3.二叉树结点的插入:
void insert(node* &root, int x) {
if(root == NULL) {
root = newNode(x);
return;
}
if(x应该插在左子树) insert(root->lchild, x);
else insert(root->rchild, x);
}
根节点指针 root 为什么使用引用?
insert(root, x) 中的 root 是上一层里的 root->lchild / root->rchild,如果不用引用,改不了上一层的 struct,也就不能把新结点接到二叉树上;
什么时候使用引用:新建结点时,如果只是修改或遍历,则不需加引用;
4.二叉树的创建:
node* Create(int data[], int n) {
node* root = NULL;
for(int i = 0; i < n; i++) insert(root, data[i]);
return root;
}
5.完全二叉树的存储结构:
使用数组(大小为结点上限个数-1),根结点为1号位,任意结点(编号x)的左结点编号为 2x,右结点为 2x+1;