1. 程式人生 > >資料結構——二叉樹(程式碼)

資料結構——二叉樹(程式碼)

 二叉樹

C++ 環境codeblocks17 通過

/*
二叉樹
使用了自定義的 棧 和 佇列
@CGQ 2018/10/29
*/
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stack>
using namespace std;
#define ElemType char

typedef struct BiTNode
{
    ElemType data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

#define QElemType BiTree
#define SElemType BiTree
#define MAXSIZE 1000
#define Status int
typedef struct SNode
{
    SElemType *base;
    SElemType *top;
    int stacksize;
}SqStack;

typedef struct QNode
{
    QElemType *base;
    int front;
    int rear;
}SqQueue;

Status InitStack(SqStack &S)
{// 初始化順序棧
    S.base = new SElemType[MAXSIZE];
    if(!S.base) return -1;
    S.top = S.base;
    S.stacksize = MAXSIZE;
    return 1;
}

Status Push(SqStack &S, SElemType &e)
{
    if(S.top-S.base == S.stacksize)
        return -1;
    *S.top = e;
    S.top++;
    return 1;
}

Status Pop(SqStack &S, SElemType &e)
{
    if(S.top == S.base)
        return -1;
    e = *(--S.top);
    return 1;
}

Status EmptyStack(SqStack &S)
{
    if(S.top-S.base == 0)
        return 1;
    else
        return 0;
}

Status InitQueue(SqQueue &Q)
{// 初始化順序佇列
    Q.base = new QElemType[MAXSIZE];    // 申請空間
    if(!Q.base) return -1;  // 申請失敗
    Q.front = Q.rear = 0;
    return 1;
}

QElemType QueueOut(SqQueue &Q)
{
    if(Q.front == Q.rear)
        return NULL;
    QElemType e = Q.base[Q.front];
    Q.front = (Q.front+1)%MAXSIZE;
    return e;
}

Status QueueIn(SqQueue &Q, QElemType &e)
{
    if((Q.rear+1)%MAXSIZE == Q.front)
        return -1;
    Q.base[Q.rear] = e;
    Q.rear = (Q.rear+1)%MAXSIZE;
    return 1;
}

Status EmptyQueue(SqQueue &Q)
{
    if(Q.rear==Q.front)
        return 1;
    else
        return 0;
}
//----------------------------------<end 棧和佇列>

void CreateBiTree(BiTree &T)
{// 先序建立二叉樹
    char ch;
    cin>>ch;
    if(ch == '#')
        T = NULL;
    else
    {
        T = new BiTNode;
        T->data = ch;
        CreateBiTree(T->lchild);
        CreateBiTree(T->rchild);
    }
}

void PreOrderTraverse(BiTree T)
{// 先序遞迴遍歷
    if(T)
    {
        cout<<T->data;
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
}

void InOrderTraverse(BiTree T)
{// 中序遞迴遍歷
    if(T)
    {
        InOrderTraverse(T->lchild);
        cout<<T->data;
        InOrderTraverse(T->rchild);
    }
}

void PostOrderTraverse(BiTree T)
{// 後序遞迴遍歷
    if(T)
    {
        PostOrderTraverse(T->lchild);
        PostOrderTraverse(T->rchild);
        cout<<T->data;
    }
}

void HierarchicalOrder_TraverseBiTree(BiTree T)
{// 層次遍歷二叉樹
    if(T==NULL) return; // 空樹

    BiTree p;
    SqQueue Q; InitQueue(Q);
    QueueIn(Q,T);
    while(!EmptyQueue(Q))
    {
        p = QueueOut(Q);
        cout<<p->data;    // 訪問

        if(p->lchild) QueueIn(Q,p->lchild);
        if(p->rchild) QueueIn(Q,p->rchild);
    } //<end while>
}

void InOrderTraverse_noRecursive(BiTree T)
{// 非遞迴中序遍歷二叉樹
    if(T==NULL) return ;
    SqStack s;
    BiTree p = T;
    InitStack(s);
    while(p||!EmptyStack(s))
    {
        if(p)   // p非空
        {
            // 可以在此處統計節點
            Push(s,p);
            p = p->lchild;
        }
        else    // p為空
        {
            Pop(s,p);
            cout<<p->data;
            p = p->rchild;
        }
    } //<end while>
}

/*
// 標準stack標頭檔案
void InOrderTraverse_noRecursive(BiTree T)
{// 非遞迴中序遍歷二叉樹
    if(T==NULL) return ;
    stack<BiTree> s;
    BiTree p = T;
    while(p||!s.empty())
    {
        if(p)   // p非空
        {
            // 可以在此處統計節點
            s.push(p);
            p = p->lchild;
        }
        else    // p為空
        {
            p = s.top();
            s.pop();
            cout<<p->data;
            p = p->rchild;
        }
    } //<end while>
}
*/

void PreOrderTraverse_noRecursive(BiTree T)
{// 非遞迴前序遍歷二叉樹
    if(T==NULL) return ;
    SqStack s;
    BiTree p;
    InitStack(s); p = T;
    while(p||!EmptyStack(s))
    {
        if(p)   // p非空
        {
            cout<<p->data;
            Push(s,p);
            p = p->lchild;
        }
        else    // p為空
        {
            Pop(s,p);
            p = p->rchild;
        }
    } //<end while>
}

void Count(BiTree T, int &leafCount, int &oneCount, int &twoCount)
{// 遍歷二叉樹統計節點個數--非遞迴中序遍歷
    leafCount=oneCount=twoCount=0;
    SqStack s; InitStack(s);
    BiTree p = T;
    while(p||!EmptyStack(s))    // p非空或者棧非空
    {
        if(p)   // p非空
        {
            if(p->lchild==NULL&&p->rchild==NULL)    // 葉子節點
                leafCount++;
            else if(p->lchild!=NULL&&p->rchild!=NULL)   // 二度節點
                twoCount++;
            else    // 一度節點
                oneCount++;

            Push(s,p);
            p = p->lchild;
        }
        else    // p為空
        {
            Pop(s,p);
            p = p->rchild;
        }
    }   // <end while>
}

int NodeCount(BiTree T)
{// 統計二叉樹T結點個數
    if(T == NULL)   return 0;
    else
        return NodeCount(T->lchild)+NodeCount(T->rchild)+1;
}

void CopyBiTree(BiTree T, BiTree & T2)
{// 複製一棵完全一樣的二叉樹
    if(T == NULL)   // 空樹,則遞迴結束
    {
        T2 = NULL;
        return ;
    }
    else
    {
        T2 = new BiTNode;
        T2->data = T->data;
        CopyBiTree(T->lchild,T2->lchild);   // 遞迴複製
        CopyBiTree(T->rchild,T2->rchild);   // 遞迴複製
    }// <end else>
}

void HierarchicalOrder_TraverseBiTree_Count(BiTree T, int &leafCount, int &oneCount, int &twoCount)
{// 層次遍歷二叉樹統計節點個數
    leafCount=oneCount=twoCount=0;
    if(T==NULL) return; // 空樹

    BiTree p;
    SqQueue Q; InitQueue(Q);
    QueueIn(Q,T);
    while(!EmptyQueue(Q))
    {
        p = QueueOut(Q);
        // 統計節點
        if(p->lchild==NULL&&p->rchild==NULL)    // 葉子節點
            leafCount++;
        else if(p->lchild!=NULL&&p->rchild!=NULL)   // 二度節點
            twoCount++;
        else    // 一度節點
            oneCount++;

        if(p->lchild) QueueIn(Q,p->lchild);
        if(p->rchild) QueueIn(Q,p->rchild);
    } //<end while>
}

int Width(BiTree T)
{// 層序遍歷統計二叉樹寬度
    if(T==NULL) return 0;   // 空樹寬度為0
    BiTree Q[1000], p; // Q 是佇列 存 放二叉樹節點指標,需要容量足夠大
    int front=1, rear=1, last=1; // front rear 是佇列的頭和尾,last存放某層最右邊的節點在Q中的位置
    int temp=0, maxw=0; // temp記錄同層節點個數
    Q[rear] = T;    // 根節點入隊
    while(front<=last)
    {
        p = Q[front++]; temp++;
        if(p->lchild) Q[++rear] = p->lchild;
        if(p->rchild) Q[++rear] = p->rchild;
        if(front>last)
        {
            last = rear;    // 將下一行的最右節點的位置賦給last
            if(temp>maxw)   maxw = temp;
            temp = 0;
        }
    } //<end while>
    return maxw;
}

int Depth(BiTree &T)
{// 後序遍歷求二叉樹深度
    if(T==NULL) return 0;   // 空樹返回0
    else
    {
        int m = Depth(T->lchild);   // 遞迴計算左子樹深度
        int n = Depth(T->rchild);   // 遞迴計算右子樹深度
        if(m>n) return (m+1);
        else    return (n+1);
    }
}

int main()
{
    BiTree T;
    printf("先序建立二叉樹,請輸入:\n");
    CreateBiTree(T);
    printf("\nInOrderTraverse--遞迴中序遍歷\n");
    InOrderTraverse(T);
    printf("\nnOrderTraverse_noRecursive--非遞迴中序遍歷\n");
    InOrderTraverse_noRecursive(T);
    printf("\nPreOrderTraverse--遞迴先序遍歷\n");
    PreOrderTraverse(T);
    printf("\nPreOrderTraverse_noRecursive--非遞迴先序遍歷\n");
    PreOrderTraverse_noRecursive(T);
    printf("\nPostOrderTraverse--遞迴後序遍歷\n");
    PostOrderTraverse(T);
    printf("\nHierarchicalOrder_TraverseBiTree--層序遍歷\n");
    HierarchicalOrder_TraverseBiTree(T);

    int leafnum=0,onenum=0,twonum=0;
    HierarchicalOrder_TraverseBiTree_Count(T,leafnum,onenum,twonum);
    printf("\n層序遍歷統計節點:leafnum=%d,onenum=%d,twonum=%d\n",leafnum,onenum,twonum);
    leafnum=onenum=twonum=0;
    Count(T,leafnum,onenum,twonum);
    printf("\n非遞迴中序遍歷統計節點:leafnum=%d,onenum=%d,twonum=%d\n",leafnum,onenum,twonum);
    int width = Width(T);
    printf("\n層序遍歷統計二叉樹最大寬度:width=%d\n",width);
    int depth = Depth(T);
    printf("\n後序遍歷統計二叉樹深度:depth=%d\n",depth);
    int nodenum = NodeCount(T);
    printf("\n該二叉樹的節點個數為: nodenum=%d\n",nodenum);

    BiTree NewT;
    CopyBiTree(T,NewT);
    printf("\n複製後的二叉樹的中序遍歷:\n");
    InOrderTraverse(NewT);
}

/*
測試資料:
AB#CD###EF##HI##G##
        A
       / \
      B   E
       \  /\
        C F H
       /    /\
      D    I  G
ABD##E##CF##G##
        A
       / \
      B   C
      /\  /\
      D E F G
*/