二叉树的性质
一般二叉树性质:
- 在非空二叉树的k层上,至多有2k个节点(k>=0)
- 高度为k的二叉树中,最多有2k+1-1个节点(k>=0)
- 对于任何一棵非空的二叉树,如果叶节点个数为n0,度数为2的节点个数为n2,则有: n0 = n2 + 1
完全二叉树性质:
只有最下面的两层结点度数小于2,其余各层的结点度数都等于2,并且最下面一层的结点都集中在该层最左边得若干位置上,则此二叉树称为完全二叉树。
- 具有n个节点的完全二叉树的高度k为[log2n]
- 对于具有n个节点的完全二叉树,如果按照从上(根节点)到下(叶节点)和从左到右的顺序对二叉树中的所有节点从0开始到n-1进行编号,则对于任意的下标为k的节点,有:
- 如果k=0,则它是根节点,它没有父节点;如果k>0,则它的父节点的下标为[(i-1)/2];
- 如果2k+1 <= n-1,则下标为k的节点的左子结点的下标为2k+1;否则,下标为k的节点没有左子结点.
- 如果2k+2 <= n-1,则下标为k的节点的右子节点的下标为2k+2;否则,下标为k的节点没有右子节点
满二叉树性质:
任何结点或者是树叶,或有两颗非空子树。
在满二叉树中,叶节点的个数比分支节点的个数多1
扩充二叉树性质:
- 在扩充二叉树中,外部节点的个数比内部节点的个数多1
- 对任意扩充二叉树,外部路径长度E和内部路径长度I之间满足以下关系:E = I + 2n, 其中n是内部节点个数
二叉树的实现与周游
二叉树的顺序表示:
二叉树的顺序表示适用于完全二叉树,根据完全二叉树的第2性质,可以建立处节点之间的关系,对于一般的二叉树,可以将其扩充为完全二叉树,然后用一维数组顺序存储.
以下是程序代码:
bintree.h
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define USED 1 4 #define NOTUSED 0 5 typedef int Type; 6 7 // 二叉树节点结构体 8 typedef struct treenode 9 { 10 int nodeIndex; 11 // 标志是否为外部节点,如果是则为0,否则为1 12 int isIn; 13 // 0表示这个节点不在二叉树中,1表示在树中 14 int isUsed; 15 Type element; 16 }TreeNode; 17 18 // 二叉树结构体 19 typedef struct bintree 20 { 21 int MAXN; 22 int n; 23 TreeNode *nodelist; 24 }*Tree; 25 26 // 创建最大节点为m的空二叉树 27 Tree createBinTree(int m) 28 { 29 int i; 30 Tree tree = NULL; 31 TreeNode *nodelist = NULL; 32 tree = malloc(sizeof(struct bintree)); 33 if (NULL != tree) 34 { 35 nodelist = malloc(m * sizeof(TreeNode)); 36 if (NULL != nodelist) 37 { 38 tree->MAXN = m; 39 tree->n = -1; 40 for (i = 0; i < m; i++) 41 { 42 nodelist[i].isUsed = NOTUSED; 43 nodelist[i].nodeIndex = i; 44 } 45 printf("\n"); 46 tree->nodelist = nodelist; 47 } 48 } 49 return tree; 50 } 51 52 // 在二叉树末尾加入元素 53 void inTree(Tree tree, Type x, int isIn) 54 { 55 void replaceTree(Tree, Type, int, int); 56 if (tree->n + 1 < tree->MAXN) 57 { 58 replaceTree(tree, x, tree->n + 1, isIn); 59 tree->n = tree->n + 1; 60 } 61 return; 62 } 63 64 // 替换二叉树中指定下标的元素 65 void replaceTree(Tree tree, Type x, int index, int isIn) 66 { 67 if (tree->n == -1 || (index >= 0 && index <= tree->n + 1)) 68 { 69 tree->nodelist[index].element = x; 70 tree->nodelist[index].isIn = isIn; 71 tree->nodelist[index].isUsed = USED; 72 } 73 return; 74 } 75 76 // 得到指定下标的元素 77 Type getNode(Tree tree, int index) 78 { 79 int re; 80 if (index >= 0 && index <= tree->n) 81 re = tree->nodelist[index].element; 82 return re; 83 } 84 85 // 得到父节点的元素下标 86 int parent(Tree tree, int child) 87 { 88 if (child < 0 || child > tree->n) 89 return -1; 90 else 91 return (child - 1) / 2; 92 } 93 94 // 得到右子节点的元素下标 95 int rightChild(Tree tree, int parent) 96 { 97 if (parent < 0 || parent > tree->n) 98 return -1; 99 else 100 return 2 * parent + 2; 101 } 102 103 // 得到左子节点的元素下标 104 int leftChild(Tree tree, int parent) 105 { 106 if (parent < 0 || parent > tree->n) 107 return -1; 108 else 109 return 2 * parent + 1; 110 }
这里用的是非递归的周游方法,所以要用到栈,一下是自定义的栈.
stack.h
1 #include "bintree.h" 2 typedef TreeNode DataType; 3 4 typedef struct mystack 5 { 6 //数组最大长度 7 int MAXN; 8 //指定栈顶位置 9 int index; 10 DataType *ele; 11 12 }*MyStack, Stack; 13 14 15 //创建一个空栈 16 MyStack createStack(int num) 17 { 18 MyStack stack = NULL; 19 stack = malloc(sizeof(Stack)); 20 if(stack != NULL) 21 { 22 stack->ele = malloc(sizeof(DataType) * num); 23 if(stack ->ele != NULL) 24 { 25 stack ->MAXN = num; 26 stack ->index = -1; 27 } 28 } 29 return stack; 30 } 31 32 //判断栈是否为空 33 int isEmptyStack(MyStack stack) 34 { 35 return stack ->index == -1; 36 } 37 38 //元素入栈,如果栈已经满则返回0,否则返回1 39 int push(MyStack stack, DataType x) 40 { 41 int index = stack ->index + 1; 42 if(index >= stack ->MAXN) 43 return 0; 44 else 45 { 46 stack ->ele[index] = x; 47 stack ->index = index; 48 return 1; 49 } 50 } 51 52 //元素出栈,如果栈已经为空返回0,否则返回1 53 int pop(MyStack stack) 54 { 55 if(isEmptyStack(stack)) 56 return 0; 57 else 58 { 59 stack ->index--; 60 return 1; 61 } 62 } 63 64 //取栈顶元素 65 DataType top(MyStack stack) 66 { 67 DataType get; 68 if(!isEmptyStack(stack)) 69 get = stack ->ele[stack ->index]; 70 return get; 71 }
bintree.c
1 #include "stack.h" 2 3 //访问节点信息 4 int visit(TreeNode node) 5 { 6 printf(" %d", node.element); 7 return node.nodeIndex; 8 } 9 10 //先根次序周游 11 void preOrder(Tree tree, MyStack stack) 12 { 13 int index = 0; 14 TreeNode node; 15 if(!tree->nodelist[index].isUsed) 16 return; 17 push(stack,tree->nodelist[index]); 18 while(!isEmptyStack(stack)) 19 { 20 node = top(stack); 21 pop(stack); 22 if(node.isUsed == USED) 23 { 24 index = visit(node); 25 push(stack,tree->nodelist[rightChild(tree, index)]); 26 push(stack,tree->nodelist[leftChild(tree, index)]); 27 } 28 29 } 30 } 31 32 //中根次序周游 33 void inOrder(Tree tree, MyStack stack) 34 { 35 int index = 0; 36 TreeNode node; 37 if(tree->nodelist[index].isUsed == NOTUSED) 38 return; 39 do 40 { 41 while(tree->nodelist[index].isUsed == USED) 42 { 43 push(stack,tree->nodelist[index]); 44 index = leftChild(tree, index); 45 } 46 node = top(stack); 47 pop(stack); 48 index = visit(node); 49 index = rightChild(tree,index); 50 } while(tree->nodelist[index].isUsed == USED || !isEmptyStack(stack)); 51 52 } 53 54 //后根次序周游 55 void postOrder(Tree tree, MyStack stack) 56 { 57 int index = 0, rightIndex; 58 TreeNode node; 59 if(tree->nodelist[index].isUsed == NOTUSED) 60 return; 61 while(tree->nodelist[index].isUsed == USED || !isEmptyStack(stack)) 62 { 63 while(tree->nodelist[index].isUsed == USED) 64 { 65 push(stack,tree->nodelist[index]); 66 rightIndex = rightChild(tree, index); 67 index = leftChild(tree ,index); 68 if(tree->nodelist[index].isUsed == NOTUSED) 69 index = rightIndex; 70 } 71 node = top(stack); 72 pop(stack); 73 index = visit(node); 74 //如果栈不为空,且从左子树退回,进入到右子树遍历 75 if(!isEmptyStack(stack) && index == leftChild(tree,top(stack).nodeIndex)) 76 index = rightChild(tree,top(stack).nodeIndex); 77 else tree->nodelist[index].isUsed = NOTUSED; 78 } 79 80 } 81 82 int main() 83 { 84 int m = 0, isIn = 1, j, buffer = 0; 85 Tree tree = NULL; 86 MyStack stack = NULL; 87 88 printf("请输入节点个数:"); 89 scanf("%d",&m); 90 tree = createBinTree(m); 91 stack = createStack(m); 92 printf("请输入%d个数字:",m); 93 //将0到5六个元素依次放入二叉树中 94 for(j = 0; j < m; j++) 95 { 96 scanf(" %d", &buffer); 97 inTree(tree, buffer, isIn); 98 } 99 100 printf("先根次序周游结果为:"); 101 preOrder(tree,stack); 102 printf("\n"); 103 104 printf("中根次序周游结果为:"); 105 inOrder(tree, stack); 106 printf("\n"); 107 108 printf("后根次序周游结果为:"); 109 postOrder(tree, stack); 110 printf("\n"); 111 112 return 1; 113 }
按图示二叉树输出:
输出结果为:
二叉树连接表示:
1 #include<stdio.h> 2 #include<stdlib.h> 3 typedef int DataType; 4 typedef struct treenode *TreeNode; 5 typedef struct treenode *BinTree; 6 7 struct treenode 8 { 9 DataType element; 10 TreeNode llink; 11 TreeNode rlink; 12 }; 13 14 BinTree createBinTree(DataType x) 15 { 16 BinTree tree = NULL; 17 tree = malloc(sizeof(struct treenode)); 18 tree->element = x; 19 return tree; 20 } 21 22 BinTree addToLeft(BinTree t, DataType x) 23 { 24 TreeNode node = NULL; 25 node = malloc(sizeof(struct treenode)); 26 if (node != NULL) 27 node->element = x; 28 t -> llink = node; 29 return node; 30 } 31 32 BinTree addToRight(BinTree t, DataType x) 33 { 34 TreeNode node = NULL; 35 node = malloc(sizeof(struct treenode)); 36 if (node != NULL) 37 node->element = x; 38 t-> rlink = node; 39 return node; 40 } 41 42 void visitRoot(BinTree tree) 43 { 44 printf("%d ", tree->element); 45 } 46 47 BinTree leftChild(BinTree tree) 48 { 49 return tree->llink; 50 } 51 52 BinTree rightChild(BinTree tree) 53 { 54 return tree->rlink; 55 } 56 //用递归方法 57 //先根周游 58 void preOrder(BinTree tree) 59 { 60 if(tree == NULL) 61 return; 62 visitRoot(tree); 63 preOrder(leftChild(tree)); 64 preOrder(rightChild(tree)); 65 } 66 67 //中根周游 68 void inOrder(BinTree tree) 69 { 70 if(NULL == tree) 71 return; 72 inOrder(leftChild(tree)); 73 visitRoot(tree); 74 inOrder(rightChild(tree)); 75 } 76 77 //后根周游 78 void postOrder(BinTree tree) 79 { 80 if(NULL == tree) 81 return; 82 postOrder(leftChild(tree)); 83 postOrder(rightChild(tree)); 84 visitRoot(tree); 85 } 86 87 int main() 88 { 89 BinTree left, right; 90 BinTree tree = createBinTree(5); 91 left = addToLeft(tree, 4); 92 right = addToRight(tree, 3); 93 addToLeft(left, 8); 94 addToRight(left, 7); 95 addToLeft(right, 6); 96 97 printf("先根周游次序:"); 98 preOrder(tree); 99 printf("\n"); 100 printf("中根周游次序:"); 101 inOrder(tree); 102 printf("\n"); 103 printf("后根周游算法:"); 104 postOrder(tree); 105 printf("\n"); 106 return 1; 107 }