二叉树特性及详细例子

来源:互联网 发布:ghost denim淘宝真假 编辑:程序博客网 时间:2024/06/04 19:47

二叉树的性质

一般二叉树性质:

  1. 在非空二叉树的k层上,至多有2k个节点(k>=0)
  2. 高度为k的二叉树中,最多有2k+1-1个节点(k>=0)
  3. 对于任何一棵非空的二叉树,如果叶节点个数为n0,度数为2的节点个数为n2,则有: n0 = n2 + 1

完全二叉树性质:

  1. 具有n个节点的完全二叉树的高度k为[log2n]
  2. 对于具有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. 在扩充二叉树中,外部节点的个数比内部节点的个数多1
  2. 对任意扩充二叉树,外部路径长度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 }
转载  http://www.cnblogs.com/hanyuan/archive/2012/05/10/bintree.html
原创粉丝点击