数据结构实验(五)二叉树

6-1 二叉树的遍历

就是简单的遍历

void InorderTraversal( BinTree BT ){
    if( BT == NULL ) return;
    if( BT->Left != NULL ) InorderTraversal( BT->Left );
    printf(" %c" , BT->Data);
    if( BT->Right != NULL ) InorderTraversal( BT->Right );
    
}

void PreorderTraversal( BinTree BT ){
    if( BT == NULL ) return;
    printf(" %c" , BT->Data);
    if( BT->Left != NULL ) PreorderTraversal( BT->Left );
    if( BT->Right != NULL ) PreorderTraversal( BT->Right );
}

void PostorderTraversal( BinTree BT ){
   if( BT == NULL ) return;
   if( BT->Left != NULL ) PostorderTraversal( BT->Left );
   if( BT->Right != NULL ) PostorderTraversal( BT->Right );
    printf(" %c" , BT->Data);
}

void LevelorderTraversal( BinTree BT ){
    if( BT == NULL ) return;
    BinTree q[100005] , u;
    int front = 1 , end = 1;
    q[front] = BT;
    while( front <= end ){
        u = q[front++];
        printf(" %c" , u->Data);
        if( u->Left != NULL ) q[++end] = u->Left;
        if( u->Right != NULL ) q[++end] = u->Right;
    }
}

6-2 二叉树求深度和叶子数

一个点的深度就是父亲的深度+1,一个节点的叶子数就是他所有子树的叶子数之和

int GetDepthOfBiTree( BiTree T ){
    if( T == NULL ) return 0;
    if( T->lchild == NULL && T->rchild == NULL ) return 1;
    int ldep , rdep;
    
    if( T->lchild != NULL ) ldep = GetDepthOfBiTree( T->lchild );
    else ldep = 0;
    
    if( T->rchild != NULL ) rdep = GetDepthOfBiTree( T->rchild );
    else rdep = 0;
    
    if( ldep > rdep ) return ldep + 1;
    else return rdep + 1;
}

int LeafCount( BiTree T ){
    if( T == NULL ) return 0;
    if( T->lchild == NULL && T->rchild == NULL ) return 1;
    
    int lLeaf = 0 , rLeaf = 0;
    if( T->lchild != NULL ) lLeaf = LeafCount( T->lchild );
    if( T->rchild != NULL ) rLeaf = LeafCount( T->rchild );
    return lLeaf + rLeaf;
}

6-3 二叉树的非递归遍历

用栈模拟一下就好,很简单

void InorderTraversal( BinTree BT ){
    if( BT == NULL ) return ;
    int vis[512];
    memset( vis , 0 , sizeof(vis) );
    Stack s = CreateStack();
    Push( s , BT );
    while( !IsEmpty (s) ){
        BinTree t = Peek(s);
        if( t->Left != NULL && vis[t->Left->Data] == 0){
            vis[t->Left->Data] = 1;
            Push( s , t->Left );
        }
        else{
            printf(" %c" , t->Data );
            Pop(s);
            if( t->Right != NULL ){
                Push( s , t->Right );
            }
        }
    }
    return ;
    
}


void PreorderTraversal( BinTree BT ){
    if( BT == NULL ) return ;
    Stack s = CreateStack();
    Push( s , BT );
    while( !IsEmpty( s ) ){
        BinTree t = Pop( s );
        printf(" %c" , t->Data );
        if( t->Right != NULL ) Push( s , t->Right );
        if( t->Left != NULL  ) Push( s , t->Left );
    }
}

void PostorderTraversal( BinTree BT ){
    if( BT == NULL ) return ;
    int vis[512];
    memset( vis , 0 , sizeof(vis) );
    Stack s = CreateStack();
    Push( s , BT );
    while( !IsEmpty(s) ){
        BinTree t = Peek(s);
        if( t->Left != NULL && vis[t->Left->Data] == 0 ){
            vis[t->Left->Data] = 1;
            Push( s , t->Left );
        }
        else if( t->Right != NULL && vis[t->Right->Data] == 0 ){
            vis[t->Right->Data] = 1;
            Push( s , t->Right );
        }
        else{
            printf(" %c" , t->Data );
            Pop(s);
        }
    }
    return ;
}

6-4 哈夫曼树及哈夫曼编码

模板算法

void reverse(char *CH){
	int n=strlen(CH);
	for ( int i=0 , j = n-1 ;  i<n/2 ; i++ , j -- )
		CH[i] ^= CH[j] ^= CH[i] ^= CH[j];
}

void SelectTwoMin(int upbound, HuffmanTree HT, int &s1, int &s2){
    int val1 = 0x7f7f7f7f , val2 = 0x7f7f7f7f;
    s1 = s2 = 0;
    for( int i = 1 ; i <= upbound ; i ++ ){
        if( HT[i].parent == 0 ){
            if( HT[i].weight < val1 ) s2 = s1 , s1 = i , val2 = val1 , val1 = HT[i].weight;
            else if( HT[i].weight < val2 ) s2 = i , val2 = HT[i].weight;
        }
    }
}

void dfs( int x , const int len , char s[] , HuffmanTree HT , HuffmanCode &HC ){
    if( HT[x].lchild == 0 && HT[x].rchild == 0 ){
        HC[x] = new char[len];
        for( int i = 0 ; i < len ; i ++ )
            HC[x][i] = s[i];
        return ;
    }
    
    char t[len];
    for( int i = 0 ; i < len ; i ++ ) t[i] = s[i];
    t[len] = '0' , dfs( HT[x].lchild , len+1 , t , HT , HC );
    t[len] = '1' , dfs( HT[x].rchild , len+1 , t , HT , HC );
    
}

void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n){
    HT = ( HuffmanTree ) malloc( (2*n+5) * sizeof(HTNode) );
    for( int i = 1 ; i <= n ; i ++ ){
        HT[i].weight = w[i-1] , HT[i].parent = HT[i].lchild = HT[i].rchild = 0;
    }
    for( int i = n+1 , s1 , s2 ; i <= 2*n-1 ; i ++ ){
        SelectTwoMin( i-1 , HT , s1 , s2 );
        HT[i].weight = HT[s1].weight + HT[s2].weight;
        HT[i].parent = 0 , HT[s1].parent = HT[s2].parent = i;
        HT[i].lchild = s1 , HT[i].rchild = s2;
    }
    HC = new char *[n+1];
    dfs( 2*n-1 , 0 , "" , HT , HC );
}


7-1 完全二叉树的层序遍历

最简单的做法就是 bfs,但是记录深度也可以用 dfs

#include<bits/stdc++.h>

using namespace std;

const int N = 35;
int a[N] , p[N] , n , t ;

void dfs( int i  ){
    if( i > n ) return;
    p[i] = a[t] , t --;
    dfs( i * 2 + 1 );
    dfs( i * 2 );
}

int32_t main() {
    cin >> n;
    for( int i = 1 ; i <= n ; i ++ )
        cin >> a[i];
    t = n , dfs( 1 );
    for( int i = 1 ; i <= n ; i ++ )
        cout << p[i] << ( i != n ? " " : "\n" );
    return 0;
}

7-2 浪漫侧影

二叉树的还原?

#include<bits/stdc++.h>
using namespace std;

const int N = 35;
int a[N] , p[N] , n ;

vector<int> resL , resR;
vector< vector<int> >res;

struct Node{
    int value;
    Node * left , * right;

    Node(): value(-1) , left(nullptr) , right(nullptr) {};

    void build( vector<int> Ino , vector<int> Suf ){
        value = Suf.back() , left = new Node() , right = new Node();
        int t = 0;
        for( auto it : Ino ){
            if( it == value ) break;
            else t ++;
        }
        auto lInoBegin = Ino.begin() , lInoEnd = Ino.begin() + t;
        auto lSufBegin = Suf.begin() , lSufEnd = Suf.begin() + t;
        auto rInoBegin = Ino.begin() + t + 1 , rInoEnd = Ino.end();
        auto rSufBegin = Suf.begin() + t , rSufEnd = Suf.end() - 1;
        vector<int> lIno,lSuf,rIno,rSuf;
        lIno.assign( lInoBegin , lInoEnd );
        lSuf.assign( lSufBegin , lSufEnd );
        rIno.assign( rInoBegin , rInoEnd );
        rSuf.assign( rSufBegin , rSufEnd );
        if( !lIno.empty() ) left->build( lIno , lSuf );
        if( !rIno.empty() ) right->build( rIno , rSuf );
    }
} *root;

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

void dfs( Node * t , int dep ){
    res[dep].push_back( t->value );
    if( t->right->value != -1 ) dfs( t->right , dep + 1 );
    if( t->left->value != -1 ) dfs( t->left , dep + 1 );
    return;
}


int32_t main() {
    int n = read();
    vector<int> Ino , Suf;
    res.resize(n);
    for( int i = 1 , x ; i <= n ; i ++ )
        x = read() , Ino.push_back( x );
    for( int i = 1 , x ; i <= n ; i ++ )
        x = read() , Suf.push_back( x );
    root = new Node();
    root->build( Ino , Suf );
    resL.push_back( root->value );
    resR.push_back( root->value );
    dfs( root , 0 );
    cout << "R:";
    for( auto it : res ){
        if( it.empty() ) break;
        cout << " " << it.front();
    }
    cout << "\nL:";
    for( auto it : res ){
        if( it.empty() ) break;
        cout << " " << it.back();
    }
    cout << "\n";
    return 0;
}
posted @ 2022-11-26 17:25  PHarr  阅读(54)  评论(0编辑  收藏  举报