zoukankan      html  css  js  c++  java
  • 二叉树特性及详细例子

    二叉树的性质

    一般二叉树性质:

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

    完全二叉树性质:
    只有最下面的两层结点度数小于2,其余各层的结点度数都等于2,并且最下面一层的结点都集中在该层最左边得若干位置上,则此二叉树称为完全二叉树。

    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     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 }

     

  • 相关阅读:
    什么是浮动IP
    How can I detect multiple logins into a Django web application from different locations?
    git add -A使用说明
    理解水平扩展和垂直扩展
    php != 和 !== 的区别
    wireshark:Couldn't run /usr/bin/dumpcap in child process: Permission denied
    Unable to VNC onto Centos server remotely
    systemctl使用说明
    KiB、MiB与KB、MB的区别
    python带setup.py的包的安装
  • 原文地址:https://www.cnblogs.com/hanyuan/p/bintree.html
Copyright © 2011-2022 走看看