資料結構——二叉樹(程式碼)
阿新 • • 發佈:2018-11-04
二叉樹
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 */