#include<iostream>
#include<queue>
#include<stack>
using namespace std; //二叉樹結點的描述
typedef struct BiTNode
{ char data; struct BiTNode *lchild, *rchild; //左右孩子
}BiTNode,*BiTree; //按先序遍歷創建二叉樹
//BiTree *CreateBiTree() //返回結點指針類型
//void CreateBiTree(BiTree &root) //引用類型的參數
void CreateBiTree(BiTNode **root) //二級指針作為函數參數
{ char ch; //要插入的數據 scanf("\n%c", &ch); //cin>>ch; if(ch=='#') *root = NULL; else { *root = (BiTNode *)malloc(sizeof(BiTNode)); (*root)->data = ch; printf("請輸入%c的左孩子:",ch); CreateBiTree(&((*root)->lchild)); printf("請輸入%c的右孩子:",ch); CreateBiTree(&((*root)->rchild)); }
} //前序遍歷的算法程序
void PreOrder(BiTNode *root)
{ if(root==NULL) return ; printf("%c ", root->data); //輸出數據 PreOrder(root->lchild); //遞歸調用,前序遍歷左子樹 PreOrder(root->rchild); //遞歸調用,前序遍歷右子樹
} //中序遍歷的算法程序
void InOrder(BiTNode *root)
{ if(root==NULL) return ; InOrder(root->lchild); //遞歸調用,前序遍歷左子樹 printf("%c ", root->data); //輸出數據 InOrder(root->rchild); //遞歸調用,前序遍歷右子樹
} //后序遍歷的算法程序
void PostOrder(BiTNode *root)
{ if(root==NULL) return ; PostOrder(root->lchild); //遞歸調用,前序遍歷左子樹 PostOrder(root->rchild); //遞歸調用,前序遍歷右子樹 printf("%c ", root->data); //輸出數據
} /*
二叉樹的非遞歸前序遍歷,前序遍歷思想:先讓根進棧,只要棧不為空,就可以做彈出操作,
每次彈出一個結點,記得把它的左右結點都進棧,記得右子樹先進棧,這樣可以保證右子樹在棧中總處于左子樹的下面。
*/
void PreOrder_Nonrecursive(BiTree T) //先序遍歷的非遞歸
{ if(!T) return ; stack<BiTree> s; s.push(T); while(!s.empty()) { BiTree temp = s.top(); cout<<temp->data<<" "; s.pop(); if(temp->rchild) s.push(temp->rchild); if(temp->lchild) s.push(temp->lchild); }
} void PreOrder_Nonrecursive1(BiTree T) //先序遍歷的非遞歸
{ if(!T) return ; stack<BiTree> s; BiTree curr = T; while(curr != NULL || !s.empty()) { while(curr != NULL) { cout<<curr->data<<" "; s.push(curr); curr = curr->lchild; } if(!s.empty()) { curr = s.top(); s.pop(); curr = curr->rchild; } }
} void PreOrder_Nonrecursive2(BiTree T) //先序遍歷的非遞歸
{ if(!T) return ; stack<BiTree> s; while(T) // 左子樹上的節點全部壓入到棧中 { s.push(T); cout<<T->data<<" "; T = T->lchild; } while(!s.empty()) { BiTree temp = s.top()->rchild; // 棧頂元素的右子樹 s.pop(); // 彈出棧頂元素 while(temp) // 棧頂元素存在右子樹,則對右子樹同樣遍歷到最下方 { cout<<temp->data<<" "; s.push(temp); temp = temp->lchild; } }
} void InOrderTraverse1(BiTree T) // 中序遍歷的非遞歸
{ if(!T) return ; BiTree curr = T; // 指向當前要檢查的節點 stack<BiTree> s; while(curr != NULL || !s.empty()) { while(curr != NULL) { s.push(curr); curr = curr->lchild; }//while if(!s.empty()) { curr = s.top(); s.pop(); cout<<curr->data<<" "; curr = curr->rchild; } }
} void InOrderTraverse(BiTree T) // 中序遍歷的非遞歸
{ if(!T) return ; stack<BiTree> s; BiTree curr = T->lchild; // 指向當前要檢查的節點 s.push(T); while(curr != NULL || !s.empty()) { while(curr != NULL) // 一直向左走 { s.push(curr); curr = curr->lchild; } curr = s.top(); s.pop(); cout<<curr->data<<" "; curr = curr->rchild; }
} void PostOrder_Nonrecursive1(BiTree T) // 后序遍歷的非遞歸
{ stack<BiTree> S; BiTree curr = T ; // 指向當前要檢查的節點 BiTree previsited = NULL; // 指向前一個被訪問的節點 while(curr != NULL || !S.empty()) // 棧空時結束 { while(curr != NULL) // 一直向左走直到為空 { S.push(curr); curr = curr->lchild; } curr = S.top(); // 當前節點的右孩子如果為空或者已經被訪問,則訪問當前節點 if(curr->rchild == NULL || curr->rchild == previsited) { cout<<curr->data<<" "; previsited = curr; S.pop(); curr = NULL; } else curr = curr->rchild; // 否則訪問右孩子 }
} void PostOrder_Nonrecursive(BiTree T) // 后序遍歷的非遞歸 雙棧法
{ stack<BiTree> s1 , s2; BiTree curr ; // 指向當前要檢查的節點 s1.push(T); while(!s1.empty()) // 棧空時結束 { curr = s1.top(); s1.pop(); s2.push(curr); if(curr->lchild) s1.push(curr->lchild); if(curr->rchild) s1.push(curr->rchild); } while(!s2.empty()) { printf("%c ", s2.top()->data); s2.pop(); }
} int visit(BiTree T)
{ if(T) { printf("%c ",T->data); return 1; } else return 0;
} void LeverTraverse(BiTree T) //方法一、非遞歸層次遍歷二叉樹
{ queue <BiTree> Q; BiTree p; p = T; if(visit(p)==1) Q.push(p); while(!Q.empty()) { p = Q.front(); Q.pop(); if(visit(p->lchild) == 1) Q.push(p->lchild); if(visit(p->rchild) == 1) Q.push(p->rchild); }
}
void LevelOrder(BiTree BT) //方法二、非遞歸層次遍歷二叉樹
{ BiTNode *queue[10];//定義隊列有十個空間 if (BT==NULL) return; int front,rear; front=rear=0; queue[rear++]=BT; while(front!=rear)//如果隊尾指針不等于對頭指針時 { cout<<queue[front]->data<<" "; //輸出遍歷結果 if(queue[front]->lchild!=NULL) //將隊首結點的左孩子指針入隊列 { queue[rear]=queue[front]->lchild; rear++; //隊尾指針后移一位 } if(queue[front]->rchild!=NULL) { queue[rear]=queue[front]->rchild; //將隊首結點的右孩子指針入隊列 rear++; //隊尾指針后移一位 } front++; //對頭指針后移一位 }
} int depth(BiTNode *T) //樹的深度
{ if(!T) return 0; int d1,d2; d1=depth(T->lchild); d2=depth(T->rchild); return (d1>d2?d1:d2)+1; //return (depth(T->lchild)>depth(T->rchild)?depth(T->lchild):depth(T->rchild))+1;
}
int CountNode(BiTNode *T)
{ if(T == NULL) return 0; return 1+CountNode(T->lchild)+CountNode(T->rchild);
} int main(void)
{ BiTNode *root=NULL; //定義一個根結點 int flag=1,k; printf(" 本程序實現二叉樹的基本操作。\n"); printf("可以進行建立二叉樹,遞歸先序、中序、后序遍歷,非遞歸先序、中序遍歷及非遞歸層序遍歷等操作。\n"); while(flag) { printf("\n"); printf("|--------------------------------------------------------------|\n"); printf("| 二叉樹的基本操作如下: |\n"); printf("| 0.創建二叉樹 |\n"); printf("| 1.遞歸先序遍歷 |\n"); printf("| 2.遞歸中序遍歷 |\n"); printf("| 3.遞歸后序遍歷 |\n"); printf("| 4.非遞歸先序遍歷 |\n"); printf("| 5.非遞歸中序遍歷 |\n"); printf("| 6.非遞歸后序遍歷 |\n"); printf("| 7.非遞歸層序遍歷 |\n"); printf("| 8.二叉樹的深度 |\n"); printf("| 9.二叉樹的結點個數 |\n"); printf("| 10.退出程序 |\n"); printf("|--------------------------------------------------------------|\n"); printf(" 請選擇功能:"); scanf("%d",&k); switch(k) { case 0: printf("請建立二叉樹并輸入二叉樹的根節點:"); CreateBiTree(&root); break; case 1: if(root) { printf("遞歸先序遍歷二叉樹的結果為:"); PreOrder(root); printf("\n"); } else printf(" 二叉樹為空!\n"); break; case 2: if(root) { printf("遞歸中序遍歷二叉樹的結果為:"); InOrder(root); printf("\n"); } else printf(" 二叉樹為空!\n"); break; case 3: if(root) { printf("遞歸后序遍歷二叉樹的結果為:"); PostOrder(root); printf("\n"); } else printf(" 二叉樹為空!\n"); break; case 4: if(root) { printf("非遞歸先序遍歷二叉樹:"); PreOrder_Nonrecursive1(root); printf("\n"); } else printf(" 二叉樹為空!\n"); break; case 5: if(root) { printf("非遞歸中序遍歷二叉樹:"); InOrderTraverse1(root); printf("\n"); } else printf(" 二叉樹為空!\n"); break; case 6: if(root) { printf("非遞歸后序遍歷二叉樹:"); PostOrder_Nonrecursive(root); printf("\n"); } else printf(" 二叉樹為空!\n"); break; case 7: if(root) { printf("非遞歸層序遍歷二叉樹:"); //LeverTraverse(root); LevelOrder(root); printf("\n"); } else printf(" 二叉樹為空!\n"); break; case 8: if(root) printf("這棵二叉樹的深度為:%d\n",depth(root)); else printf(" 二叉樹為空!\n"); break; case 9: if(root) printf("這棵二叉樹的結點個數為:%d\n",CountNode(root)); else printf(" 二叉樹為空!\n"); break; default: flag=0; printf("程序運行結束,按任意鍵退出!\n"); } } system("pause"); return 0;
}