zoukankan      html  css  js  c++  java
  • [Algorithm]树与二叉树

    一.树与二叉树相关算法


    1.二叉树按顺序结构存储,求编号为i和j的两个结点的最近公共祖先结点的值

    1 ElemType CommonAncestor( SeqTree T, int i, int j )
    2 {
    3     while ( i != j )
    4     {
    5         if ( i > j ) i /= 2;
    6         else j /= 2;
    7     }
    8     return T[i];
    9 }

    2.二叉树前序遍历非递归算法

     1 void PreOrder( BiTree T )
     2 {
     3     BiTree S[MAXSIZE], p;
     4     int top = -1;
     5     p = T;
     6     while ( p || top != -1 )
     7     {
     8         if (p)
     9         {
    10             visit( p );
    11             S[++top] = p; p = p->lchild;
    12         }
    13         else
    14         {
    15             p = S[top--]; p = p->rchild;
    16         }
    17     }
    18 }

    3.二叉树中序遍历非递归算法

     1 void InOrder( BiTree T )
     2 {
     3     BiTree S[MAXSIZE], p;
     4     int top = -1;
     5     p = T;
     6     while ( p || top != -1 )
     7     {
     8         if (p )
     9         {
    10             S[++top] = p; p = p->lchild;
    11         }
    12         else
    13         {
    14             p = S[top--]; visit( p ); p = p->rchild;
    15         }
    16     }
    17 }

    4.二叉树后序遍历非递归算法

     1 void PostOrder( BiTree T )
     2 {
     3     BiTree Q[MAXSIZE], p, r;
     4     int top = -1;
     5     p = T; r = NULL;
     6     while ( p || top != -1 )
     7     {
     8         if (p)    // 走到最左边
     9         {
    10             S[++top] = p; p = p->lchild;
    11         }
    12         else    // 向右
    13         {
    14             p = S[top];
    15             if (p->rchild&&p->rchild!=r)    // 转向右
    16                 p = p->rchild;
    17             else    // 根
    18             {
    19                 p = S[top--];
    20                 visit( p );
    21                 r = p;
    22                 p = NULL;
    23             }
    24         }
    25     }
    26 }

    5.二叉树层次遍历算法

     1 void LevelOrder( BiTree T )
     2 {
     3     BiTree Q[MAXSIZE], p;
     4     int front = -1, rear = -1;
     5     Q[++rear] = T;
     6     while ( front != rear )
     7     {
     8         p = Q[++front];
     9         visit( p );
    10         if ( p->lchild ) Q[++rear] = p->lchild;
    11         if ( p->rchild ) Q[++rear] = p->rchild;
    12     }
    13 }

    6.二叉树的自下而上,从右到左的层次遍历算法

     1 void InvertLevel( BiTree T )
     2 {
     3     BiTree S[MAXSIZE], Q[MAXSIZE], p;
     4     int front = -1, rear = -1, top = -1;
     5     Q[++rear] = T;
     6     while ( front != rear )
     7     {
     8         p = Q[++front];
     9         S[++top] = p;
    10         if ( p->lchild ) Q[++rear] = p->lchild;
    11         if ( p->rchild ) Q[++rear] = p->rchild;
    12     }
    13     while ( top!=-1 )
    14     {
    15         p = S[top--]; visit( p );
    16     }
    17 }

    7.求二叉树高度(递归)

    1 int BtDepth( BiTree T )
    2 {
    3     if ( T == NULL ) return 0;
    4     int ldepth, rdepth;
    5     ldepth = BtDepth( T->lchild );
    6     rdepth = BtDepth( T->rchild );
    7     return ldepth > rdepth ? ldepth + 1 : rdepth + 1;
    8 }

    8.求二叉树高度(非递归)

     1 // 法一思路:后序遍历,最大栈长即为树的高度
     2 int BtDepth( BiTree T )
     3 {
     4     BiTree S[MAXSIZE], p, r;
     5     int top = -1, depth = 0;
     6     while ( p || top != -1 )
     7     {
     8         if ( p )
     9         {
    10             S[++top] = p; p = p->lchild;
    11         }
    12         else
    13         {
    14             p = S[top];
    15             if ( p->rchild&&p->rchild != r )
    16                 p = p->rchild;
    17             else
    18             {
    19                 if (top+1>depth)
    20                     depth = top + 1;
    21                 p = S[top--];
    22                 r = p;
    23                 p = NULL;
    24             }
    25         }
    26     }
    27     return depth;
    28 }
     1 // 法二思路:层次遍历,层数即为高度
     2 int BtDepth( BiTree T )
     3 {
     4     BiTree Q[MAXSIZE], p;
     5     int front = -1, rear = -1, last = 0, depth = 0;
     6     Q[++rear] = T;
     7     while ( front != rear )
     8     {
     9         p = Q[++front];
    10         if ( p->lchild )
    11             Q[++rear] = p->lchild;
    12         if ( p->rchild )
    13             Q[++rear] = p->rchild;
    14         if ( front == last )
    15         {
    16             depth++;
    17             last = rear;
    18         }
    19     }
    20     return depth;
    21 }

    9.先许遍历序列和中序遍历序列分别存放于两个一维数组$A[1...n],B[1...n]$中,编写算法建立该二叉树的二叉链表

     1 BiTree PreInCreate( ElemType A[], ElemType B[], int l1, int h1, int l2, int h2 )
     2 {
     3     BiTree root = ( BiTree ) malloc( sizeof( BiTNode ) );
     4     int i, llen, rlen;
     5     root->data = A[l1];
     6     for ( i = l2; B[i] != root->data; i++ );
     7     llen = i - l2;
     8     rlen = h2 - i;
     9     if ( llen )
    10         root->lchild = PreInCreate( A, B, l1 + 1, l1 + llen, l2, l2 + llen - 1 );
    11     else
    12         root->rchild = NULL;
    13     if ( rlen )
    14         root->rchild = PreInCreate( A, B, h1 - rlen + 1, h1, h2 - rlen + 1, h2 );
    15     else
    16         root->rchild = NULL;
    17     return root;
    18 }

     10.判断二叉树是否是完全二叉树

     1 bool IsComplete( BiTree T )
     2 {
     3     if ( T == NULL ) return true;
     4     BiTree Q[MAXSIZE], p;
     5     int front = -1, rear = -1;
     6     Q[++rear] = T;
     7     while ( front != rear )
     8     {
     9         p = Q[++front];
    10         if (p)
    11         {
    12             Q[++rear] = p->lchild;
    13             Q[++rear] = p->rchild;
    14         } 
    15         else
    16         {
    17             while ( front != rear )
    18             {
    19                 p = Q[++front];
    20                 if ( p ) return false;
    21             }
    22         }
    23     }
    24     return true;
    25 }

    11.计算一棵给定二叉树的所有双分支结点个数

    1 int N2Nodes( BiTree T )
    2 {
    3     if ( T == NULL ) return 0;
    4     if ( T->lchild && T->rchild )
    5         return N2Nodes( T->lchild ) + N2Nodes( T->rchild ) + 1;
    6     return N2Nodes( T->lchild ) + N2Nodes( T->rchild );
    7 }

    12.将二叉树中所有结点的左,右子树进行交换

    1 void SwapTree( BiTree T )
    2 {
    3     if ( T == NULL ) return;
    4     SwapTree( T->lchild );
    5     SwapTree( T->rchild );
    6     swap( T->lchild, T->rchild );
    7 }

    13.求二叉树先序遍历序列中第$k(1le kle ext 二叉树结点个数)$个结点的值

     1 int i = 1;
     2 ElemType PreNodeK( BiTree T, int k )
     3 {
     4     if ( T == NULL ) return '#';
     5     if ( i == k ) return T->data;
     6     i++;    // 下一个结点
     7     ElemType ch = PreNodeK( T->lchild, k );
     8     if ( ch != '#' ) return ch;
     9     ch = PreNodeK( T->rchild, k );
    10     return ch;
    11 }

    14.二叉树中,对于每一个元素值为x的结点,删去以它为根的子树,并释放相应的空间

    1 void DeleteNode( BiTree T )
    2 {
    3     if ( T == NULL ) return;
    4     DeleteNode( T->lchild );
    5     DeleteNode( T->rchild );
    6     free( T );
    7 }
     1 // 法一:递归
     2 void DeleteAllXNode( BiTree T, ElemType x )
     3 {
     4     if ( T == NULL ) return;
     5     if ( T->data == x )
     6     {
     7         DeleteNode( T ); return;
     8     }
     9     DeleteAllXNode( T->lchild, x );
    10     DeleteAllXNode( T->rchild, x );
    11 }
     1 // 法二:非递归
     2 void DeleteAllXNode( BiTree T, ElemType x )
     3 {
     4     if ( T == NULL ) return;
     5     BiTree Q[MAXSIZE], p;
     6     int front = -1, rear = -1;
     7     Q[++rear] = T;
     8     while ( front != rear )
     9     {
    10         p = Q[++front];
    11         if ( p->data == x ) DeleteNode( p );
    12         else
    13         {
    14             if ( p->lchild ) Q[++rear] = p->lchild;
    15             if ( p->rchild ) Q[++rear] = p->rchild;
    16         }
    17     }
    18 }

    15.输出二叉树中值为x的结点$(le 1)$个的所有祖先

     1 // 法一:递归
     2 bool AllAncestorX( BiTree T, ElemType x )
     3 {
     4     if ( T == NULL ) return false;
     5     if ( T->data == x ) return true;
     6     bool b1, b2;
     7     b1 = AllAncestorX( T->lchild, x );
     8     b2 = AllAncestorX( T->rchild, x );
     9     if ( b1 || b2 ) visit( T );
    10     return b1 || b2;
    11 }
     1 // 法二:非递归
     2 // 思路: 后序遍历非递归方式中,保留在栈中所有元素(除栈顶外)必然是栈顶的祖先结点,只要找到x结点,将所有结点出栈即可
     3 void AllAncestorX( BiTree T, ElemType x )
     4 {
     5     if ( T == NULL ) return;
     6     BiTree S[MAXSIZE], p, r;
     7     int top = -1;
     8     p = T; r = NULL;
     9     while ( p||top!=-1 )
    10     {
    11         if (p)
    12         {
    13             S[++top] = p; p = p->lchild;
    14         }
    15         else
    16         {
    17             p = S[top];
    18             if ( p->rchild&&p->rchild != r )
    19                 p = p->rchild;
    20             else
    21             {
    22                 p = S[top--];
    23                 if (p->data==x)
    24                 {
    25                     while ( top != -1 )
    26                     {
    27                         p = S[top--]; visit( p );
    28                     }
    29                 }
    30                 r = p;
    31                 p = NULL;
    32             }
    33         }
    34     }
    35 }

    16.p,q为二叉树中任意两个结点的指针,编写算法找到p,q的最近公共祖先结点(递归)

     1 // 思路:   ①左子树中能找到p(或q),右子树中能找到q(或p),的结点一定为p,q的最近公共结点
     2 //        ②p,q都在右子树上,则深度低的为公共祖先
     3 //        ③p,q都在左子树上,则深度低的为公共祖先
     4 //    三种情况       o  <-root(此时为公共祖先)      o  <-root                             o <-root
     5 //                /                                                                /
     6 //           p-> o   o  <-q                       o  <-p(此时为公共祖先为right)        o  <-p(此时为公共祖先left)
     7 //                                                                                /
     8 //                                                  o  <-q                        o  <-q
     9 BiTree Ancestor( BiTree root, BiTNode *p, BiTNode *q )
    10 {
    11     if ( !root || !p || !q ) return NULL;
    12     if ( p == root || q == root ) return root;
    13     BiTree left, right;
    14     /* 
    15      * ①在左子树中,若找到p,q中一个,则返回一个
    16      * ②在左子树中,若找到p,q(全),则返回较近的一个(高度较低的)
    17      */
    18     left = Ancestor( root->lchild, p, q );
    19     /*
    20     * ①在右子树中,若找到p,q中一个,则返回一个
    21     * ②在右子树中,若找到p,q(全),则返回较近的一个(高度较低的)
    22     */
    23     right = Ancestor( root->rchild, p, q );    
    24     if ( left&&right ) return root;
    25     return left ? left : right;
    26 }

    17.求非空二叉树的宽度

     1 int TreeWidth( BiTree T )
     2 {
     3     BiTree Q[MAXSIZE], p;
     4     int front = -1, rear = -1, maxWidth = 0;
     5     Q[++rear] = T;
     6     while ( front != rear )
     7     {
     8         int width = rear - front;
     9         if ( maxWidth < width )
    10             maxWidth = width;
    11         while ( width-- )
    12         {
    13             p = Q[++front];
    14             if ( p->lchild ) Q[++rear] = p->lchild;
    15             if ( p->rchild ) Q[++rear] = p->rchild;
    16         }
    17     }
    18     return maxWidth;
    19 }

    18.一棵满二叉树(所有结点值均不同),已知其先序序列为pre,设计算法求其后序序列post

     1 // 思路: 每次都会确定出后序的一个位置并划分为左右两块,再分别在这左右两块中继续确定其他元素 
     2 //  先序: x|    |    |
     3 //  后序: |    |    |x
     4 void PreToPost( ElemType pre[], int l1, int h1, ElemType post[], int l2, int h2 )
     5 {
     6     if ( h1 < l1 ) return;
     7     post[h2] = pre[l1]; // 确定出一个后序位置
     8     int half = ( h1 - l1 ) / 2;
     9     PreToPost( pre, l1 + 1, l1 + half, post, l2, l2 + half - 1 );
    10     PreToPost( pre, h1 - half + 1, h1, post, h2 - half, h2 - 1 );
    11 }

    19.将二叉树叶子结点按从左到右连成单链表,表头指针为head,叶结点的右指针域存放单链表指针

     1 BiTree head, pre = NULL;
     2 BiTree InOrder( BiTree bt )
     3 {
     4     if ( bt == NULL ) return NULL;
     5     InOrder( bt->lchild );
     6     if ( !bt->lchild && !bt->rchild )
     7     {
     8         if (!pre)
     9         {
    10             head = pre = bt;
    11         }
    12         else
    13         {
    14             pre->rchild = bt; pre = bt;
    15         }
    16     }
    17     InOrder( bt->rchild );
    18     pre->rchild = NULL;
    19     return head;
    20 }

    20.判断两棵二叉树是否相似.(注:不要求结点值相同,只要树的外形相同即可)

     1 bool Similar( BiTree T1, BiTree T2 )
     2 {
     3     if ( T1 == NULL && T2 == NULL ) 
     4         return true;
     5     else if ( T1 == NULL || T2 == NULL ) 
     6         return false;
     7     else if ( Similar( T1->lchild, T2->lchild ) && Similar( T1->rchild, T2->rchild ) )
     8         return true;
     9     return false;
    10 }

    21.将表达式树转换为等价的中缀表达式(通过括号反映操作符的计算次序)并输出

     1 // 思路: 表达式树的中序序列加上必要的括号即为等价的中缀表达式.除根结点外,遍历到其他结点时在遍历其左子树之前加上左括号,在遍历完右子树后加上右括号
     2 void BiTreeToExp( BiTree T, int deep )
     3 {
     4     if ( T == NULL ) return;
     5     else if ( !T->lchild && !T->rchild ) visit( T );
     6     else
     7     {
     8         if ( deep > 1 ) printf( "(" );
     9         BiTreeToExp( T->lchild, deep + 1 );
    10         visit( T );
    11         BiTreeToExp( T->rchild, deep + 1 );
    12         if ( deep > 1 ) printf( "(" );
    13     }
    14 }

    22.求孩子兄弟表示法存储的森林的叶子节点数

     1 typedef struct CSNode
     2 {
     3     ElemType data;
     4     struct CSNode *firstchild, *nextsibling;
     5 }CSNode, *CSTree;
     6 
     7 int Leaves( CSTree T )
     8 {
     9     if ( T == NULL ) return 0;
    10     if ( T->firstchild == NULL )
    11         return 1 + Leaves( T->nextsibling );
    12     else
    13         return Leaves( T->firstchild ) + Leaves( T->nextsibling );
    14 }

    23.以孩子兄弟链表为存储结构,求树的高度(深度)(递归)

    1 int Height( CSTree T )
    2 {
    3     if ( T == NULL ) return 0;
    4     int hc, hs;
    5     hc = Height( T->firstchild ) + 1;
    6     hs = Height( T->nextsibling );
    7     return hc > hs ? hc : hs;
    8 }

    24.二叉排序树的查找(非递归)

     1 BiTree BSTSearch( BiTree T, ElemType key )
     2 {
     3     while ( T && key != T->data )
     4     {
     5         if ( key < T->data )
     6             T = T->lchild;
     7         else
     8             T = T->rchild;
     9     }
    10     return T;
    11 }

     1 BiTree BSTSearch( BiTree T, ElemType key )
     2 {
     3     while ( T )
     4     {
     5         if ( T->data == key ) return T;
     6         else if ( T->data > key )
     7             T = T->lchild;
     8         else
     9             T = T->rchild;
    10     }
    11     return T;
    12 }

    25.二叉排序树的插入(递归)

     1 bool BSTInsert( BiTree& T, ElemType key )
     2 {
     3     if (!T)
     4     {
     5         T = ( BiTree ) malloc( sizeof( BiTNode ) );
     6         T->data = key;
     7         T->lchild = T->rchild = NULL;
     8         return true;
     9     }
    10     else if ( T->data == key ) return false;
    11     else if ( T->data > key ) return BSTInsert( T->lchild, key );
    12     else return BSTInsert( T->rchild, key );
    13 }

    26.计算二叉树的带权路径长度(递归)

     1 int wpl = 0;
     2 int WPL_PreOrder( BiTree T, int deep )
     3 {
     4     if ( T == NULL ) return 0;
     5     if ( !T->lchild && !T->rchild )
     6         wpl += deep * T->weight;
     7     else
     8     {
     9         if ( T->lchild ) WPL_PreOrder( T->lchild, deep + 1 );
    10         if ( T->rchild ) WPL_PreOrder( T->rchild, deep + 1 );
    11     }
    12     return wpl;
    13 }

    27.计算二叉树的带权路径长度(非递归)

     1 // 思路: 层序遍历的思想
     2 int wpl = 0;
     3 int WPL_LevelOrder( BiTree T )
     4 {
     5     if ( T == NULL ) return 0;
     6     BiTree Q[MAXSIZE], p;
     7     int front = -1, rear = -1, depth = 0, last = 0;
     8     Q[++rear] = T;
     9     while ( front != rear )
    10     {
    11         p = Q[++front];
    12         if ( !p->lchild && !p->rchild )
    13             wpl += depth * p->weight;
    14         else
    15         {
    16             if ( p->lchild ) Q[++rear] = p->lchild;
    17             if ( p->rchild ) Q[++rear] = p->rchild;
    18         }
    19         if ( front == last )
    20         {
    21             depth++; last = rear;
    22         }
    23     }
    24     return wpl;
    25 }

    28.判断二叉树是否为二叉排序树

     1 ElemType preVal = MIN;
     2 bool IsBST( BiTree T )
     3 {
     4     if ( T == NULL ) return true;
     5     if ( !IsBST( T->lchild ) ) return false;
     6     if ( preVal >= T->data )
     7         return false;
     8     else
     9         preVal = T->data;
    10     if ( !IsBST( T->rchild ) ) return false;
    11     return true;
    12 }

    29.求出指定结点在二叉排序树中的层次

     1 int Level( BiTree T, BiTree p )
     2 {
     3     if ( T == NULL ) return 0;
     4     int n = 1;
     5     while ( T->data != p->data )
     6     {
     7         n++;
     8         if ( p->data < T->data )
     9             T = T->lchild;
    10         else
    11             T = T->rchild;
    12     }
    13     return n;
    14 }

    30.判断二叉树是否为平衡二叉树

     1 bool IsAVL( BiTree T, int& h )
     2 {
     3     int h1 = 0, h2 = 0;
     4     if (T==NULL )
     5     {
     6         h = 0; return true;
     7     }
     8     if ( IsAVL( T->lchild, h1 ) && IsAVL( T->rchild, h2 ) )
     9     {
    10         if ( abs( h1 - h2 ) <= 1 )
    11         {
    12             h = 1 + ( h1 > h2 ? h1 : h2 );
    13             return true;
    14         }
    15     }
    16     return false;
    17 }

    31.从大到小输出二叉排序中所有值不小于k的关键字

     1 void DesOutput( BiTree T, ElemType k )
     2 {
     3     if ( T == NULL ) return;
     4     DesOutput( T->rchild, k );
     5     if ( T->data >= k )
     6         visit( T );
     7     else
     8         return;
     9     DesOutput( T->lchild, k );
    10 }

    32.在二叉排序树上查找第$k(1le kle n)$小的元素,要求平均时间复杂度为$O(log_{2}n)$二叉排序树上的每个结点中除data,lchild,rchild外,还增加一个count成员,保存以该结点为根的子树上的结点个数

     1 // 法一
     2 BiTree SearchSmallK( BiTree T, int k )
     3 {
     4     if ( k<1 || k>T->count ) return NULL;
     5     if ( T->lchild )
     6     {
     7         if ( k <= T->lchild->count )
     8             return SearchSmallK( T->lchild, k );
     9         else if ( k == T->lchild->count + 1 )
    10             return T;
    11         else
    12             return SearchSmallK( T->rchild, k - ( T->lchild->count + 1 ) );
    13     }
    14     else
    15     {
    16         if ( k == 1 ) return T;
    17         else return SearchSmallK( T->rchild, k - 1 );
    18     }
    19 }
     1 // 法二
     2 BiTree SearchSmallK( BiTree T, int k )
     3 {
     4     if ( k<1 || k>T->count ) return NULL;
     5     if ( T->lchild )
     6     {
     7         if ( k <= T->lchild->count )
     8             return SearchSmallK( T->lchild, k );
     9         else
    10             k -= T->lchild->count;
    11     }
    12     if ( k == 1 ) return T;
    13     if ( T->rchild )
    14         return SearchSmallK( T->rchild, k - 1 );
    15 }

    33.对于含有$+,-,*,/$及括号的算术表达式(中缀表达式)写一个算法,将该表达式构造成相应的二叉树表示

     1 // 思想: 最后使用的操作符作为根.即:先+,-后*,/
     2 // 例如: a+b*(c-d)-e/f构造的表达式树如下:
     3 //                -
     4 //               /  
     5 //              +    /
     6 //             /   / 
     7 //            a  *  e  f
     8 //              / 
     9 //             b   -
    10 //                / 
    11 //               c   d
    12 // 通过该表达式树,可以很容易得到:
    13 // 前缀表达式: -+a*b-cd/ef
    14 // 中缀表达式: a+b*c-d-e/f
    15 // 后缀表达式: abcd-*+ef/-
    16 BiTNode* BuildTree( char* exp, int s, int e )
    17 {
    18     if ( e - s == 1 )
    19     {
    20         BiTNode* p = ( BiTNode* ) malloc( sizeof( BiTNode ) );
    21         p->data = exp[s];
    22         p->lchild = p->rchild = NULL;
    23         return p;
    24     }
    25     int c1 = -1, c2 = -1, c = 0, i;
    26     for ( i = s; i < e; i++ )
    27     {
    28         if ( exp[i] == '(' ) c++;
    29         else if ( ( exp[i] == '+' || exp[i] == '-' ) && !c )
    30             c1 = i;
    31         else if ( ( exp[i] == '*' || exp[i] == '/' ) && !c )
    32             c2 = i;
    33     }
    34     if ( c1 < 0 ) c1 = c2;
    35     if ( c1 < 0 ) return BuildTree( exp, s + 1, e - 1 );
    36     BiTree* p = ( BiTNode* ) malloc( sizeof( BiTNode ) );
    37     p->data = exp[c1];
    38     p->lchild = BuildTree( exp, s, c1 );
    39     p->rchild = BuildTree( exp, c1 + 1, e );
    40     return p;
    41 }
  • 相关阅读:
    Bitmap\Bytes\BitmapImage相互转换
    枚举值为什么使用1,2,4,8,16,32等2的幂方(转)
    获取电脑信息
    操作内存的帮助类
    C#调用DLL(整理)
    [原]java集合类TreeMap和TreeSet
    [原]《面试题精选》08.颠倒句子中单词的顺序
    [原]数据结构与对象的区别
    [原]初步了解Hadoop平台
    [原]《程序员面试题精选》06.查找最小的k个元素
  • 原文地址:https://www.cnblogs.com/brianyi/p/10179100.html
Copyright © 2011-2022 走看看