二叉树特性及详细例子
来源:互联网 发布:ar软件下载 编辑:程序博客网 时间:2024/06/05 03:16
二叉树的性质
一般二叉树性质:
- 在非空二叉树的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 else100 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 else109 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,否则返回139 int push(MyStack stack, DataType x)40 {41 int index = stack ->index + 1;42 if(index >= stack ->MAXN)43 return 0;44 else45 {46 stack ->ele[index] = x;47 stack ->index = index; 48 return 1;49 }50 }51 52 //元素出栈,如果栈已经为空返回0,否则返回153 int pop(MyStack stack)54 {55 if(isEmptyStack(stack))56 return 0;57 else58 {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 }
- 二叉树特性及详细例子
- 二叉树特性及详细例子
- 二叉树特性及证明
- MACD详细计算方法及例子
- 二叉树例子
- 二叉树的递归遍历和非递归遍历(附详细例子)
- 二叉树的递归遍历和非递归遍历(附详细例子)
- MongoDB常用命令及例子详细介绍
- MongoDB常用命令及例子详细介绍
- Android四大组件详细介绍及例子
- 树及二叉树中一些易忘的术语和特性
- 构造平衡二叉树例子
- 二叉节点及二叉树
- 详细介绍Eclipse 3.2 M5新特性及下载地址
- JDK7新特性详细说明及代码示例
- 二叉树遍历以及相关特性
- 数据结构——二叉树的特性
- 数据结构基础篇(6)--二叉树特性
- apue-笔记
- dba 常用的视图
- HDU 1016 Prime Ring Problem
- MFC--CListCtrl
- Android中raw文件夹
- 二叉树特性及详细例子
- 二分堆(binary)
- UVA 109 SCUD Busters【凸包模拟题】
- 4.Collection Underscore Methods(Official Tutorials)
- OSX: 在VirtualBox中运行BootCamp上的Windows-补遗
- UVA 10034 By ACReaper
- 数据库提示,正在使用无法还原
- 黑马程序员_GUI
- Java虚拟机(JVM)中的内存设置详解