實驗報告3 樹
1)順序二叉樹
#include <iostream> #include <stdlib.h> #include <stdio.h> #include <string> #include <string.h> #include <math.h> #define MAXSIZE 20 //順序二叉樹 using namespace std; typedef int Elemtype; typedef struct SqBinode { Elemtype data[MAXSIZE]; } SqBinode,SqBiTree; typedef struct { int level;//第幾層 int order;//本層序號,(level,order)類似於(i,j) } position; void initBiTree(SqBiTree &bt) { for (int i=0; i<MAXSIZE; i++) { bt.data[i]=NULL; } } int createBiTree(SqBiTree &bt) { cout<<"無節點處請輸入0,輸入完畢請輸入-999"<<endl; int i=0,n; cin>>n; while (n!=-999&&i<=MAXSIZE) { bt.data[i]=n; i++; if (i!=0&&bt.data[(i+1)/2-1]==NULL&&bt.data[i]!=NULL) { cout<<"存在雙親為空且自身為空且不為根節點的點!"<<endl; return 0; } cin>>n; } if (i>MAXSIZE) return 0; return 1; } int BiTreeEmpty(SqBiTree bt) { if (bt.data[0]==NULL) return 1; else return 0; } int BiTreeDepth(SqBiTree bt) { int n=0,i=0;//N為節點個數 for (i=0;i<MAXSIZE-1;i++) { if (bt.data[i]!=NULL) n++; } int k=0; do { k++; } while (pow(2,k-1)<=n); return k-1; } Elemtype Root(SqBiTree bt) { if (bt.data[0]) return bt.data[0]; else return 0; } void initPosition(position &p,int a,int b) { p.level=a; p.order=b; } void Value(SqBiTree bt,Elemtype &e,position p) { //根據E的位置P找到它 int n=pow(2,p.level-1)+p.order-2; e=bt.data[n]; } void Assign(SqBiTree &bt,position &p,Elemtype e) { int x=pow(2,p.level-1)+p.order-2; bt.data[x]=e; } void print(SqBiTree bt) { int i,j,k=0; for (i=1;i<=BiTreeDepth(bt); i++) { cout<<"第"<<i<<"層"; for (j=1; j<=pow(2,i-1); j++) { if (bt.data[k]!=NULL) cout<<"("<<j<<","<<bt.data[k]<<") "; k++; } cout<<endl; } } void valueP(int i,int j,position &p) { p.level=i; p.order=j; } int Parent(SqBiTree &bt,Elemtype e) { if (bt.data[0]==e) return NULL; int i=1; while (bt.data[i]!=e && i<=MAXSIZE-1) i++; return bt.data[(i+1)/2-1]; } int LeftChild(SqBiTree &bt,Elemtype e) { //1.葉子結點無左孩子 2.非葉子結點的左孩子是2*i int i=0; while (bt.data[i]!=e && i<=MAXSIZE-1) i++; //循環停止時應當是找到了值為E的結點,但不知道是葉子節點還是非葉子 if (bt.data[2*i+1]!=NULL) return bt.data[2*i+1]; else return NULL; } int RightChild(SqBiTree &bt,Elemtype e) { //1.葉子結點無左孩子 2.非葉子結點的左孩子是2*i int i=0; while (bt.data[i]!=e && i<=MAXSIZE-1) i++; //循環停止時應當是找到了值為E的結點,但不知道是葉子節點還是非葉子 if (bt.data[2*i+2]!=NULL) return bt.data[2*i+2]; else return NULL; } int LeftSibling(SqBiTree &bt,Elemtype e) { int i=0; if (!bt.data[0]) return NULL;//空樹不用查找 if (bt.data[0]==e) return NULL;//根節點沒有左兄弟 while (bt.data[i]!=e && i<=MAXSIZE-1) i++; //1.左兄弟為-1 2. 為最左側的一列,沒有左兄弟 if (i%2==0) return bt.data[i-1];//序號為偶節點才有左兄弟 else return NULL; } int RightSibling(SqBiTree &bt,Elemtype e) { int i=0; if (!bt.data[0]) return NULL;//空樹不用查找 if (bt.data[0]==e) return NULL;//根節點沒有左兄弟 while (bt.data[i]!=e && i<=MAXSIZE-1) i++; //1.左兄弟為-1 2. 為最左側的一列,沒有左兄弟 if (i%2!=0) return bt.data[i+1];//序號為偶節點才有左兄弟 else return NULL; } void Move(SqBiTree &bt,int k,SqBiTree &q,int g) { if (bt.data[2*k+1]!=NULL) //左孩子不空 Move(bt,2*k+1,q,2*g+1); if (bt.data[2*k+2]!=NULL)//右孩子不空 Move(bt,2*k+2,q,2*g+2); q.data[g]=bt.data[k]; bt.data[k]=NULL; } int InsertChild(SqBiTree &bt,Elemtype e,int LR,SqBiTree &c) { //1.找到E所在結點的序號 int i =0; while (bt.data[i]!=e &&i<=MAXSIZE-1 ) i++; int k=2*i+LR+1;//得到E結點的LR孩子的序號 if (bt.data[k])//如果LR結點存在,需要轉移到C的右子樹,也就是K結點的右子樹 Move(bt,k,bt,2*k+2); Move(c,0,bt,k); return 1; } void del(SqBiTree &bt ,int k) { //刪除bt的k結點作為根結點的非空樹 if (!bt.data[2*k+1])//左子樹非空 del(bt,2*k+1); if (!bt.data[2*k+2]) del(bt,2*k+2); bt.data[k]=NULL; } int DeleteChild(SqBiTree &bt,Elemtype e,int lr) { //刪除e元素對應的左或右子樹 //1 find the number of e int i=0; while (bt.data[i]!=e &&i<=MAXSIZE-1) i++; //2 找到要刪除的左或右子樹 int k =2*i+1+lr; if (bt.data[k]!=NULL) //非空則刪除 del(bt,k); else { cout<<"不存在左或右子樹,無法刪除"<<endl; return 0; } } void PreOrder(SqBiTree &bt ,int i) { cout<<bt.data[i]<<" "; if (bt.data[2*i+1])//左子樹非空 PreOrder(bt,2*i+1); if (bt.data[2*i+2])//右子樹非空 PreOrder(bt,2*i+2); } int PreOrderTraverse(SqBiTree &bt) { int i=0; if (bt.data[i]) PreOrder(bt,i);//遍歷左子樹 else { cout<<"此樹為空,不能遍歷"<<endl; return 0; } return 1; } void InOrder(SqBiTree &bt ,int i) { if (bt.data[2*i+1])//左子樹非空 PreOrder(bt,2*i+1); cout<<bt.data[i]<<" "; if (bt.data[2*i+2])//右子樹非空 PreOrder(bt,2*i+2); } int InOrderTraverse(SqBiTree &bt) { int i=0; if (bt.data[i]) InOrder(bt,i);//遍歷左子樹 else { cout<<"此樹為空,不能遍歷"<<endl; return 0; } return 1; } void PostOrder(SqBiTree &bt ,int i) { if (bt.data[2*i+1])//左子樹非空 PostOrder(bt,2*i+1); if (bt.data[2*i+2])//右子樹非空 PostOrder(bt,2*i+2); cout<<bt.data[i]<<" "; } int PostOrderTraverse(SqBiTree &bt) { int i=0; if (bt.data[i]) PostOrder(bt,i);//遍歷左子樹 else { cout<<"此樹為空,不能遍歷"<<endl; return 0; } return 1; } int main() { cout<<"---順序二叉樹的基本操作實現 twomeng---"<<endl; cout<<"--------------------------------------"<<endl; cout<<"1 InsertChild()"<<endl; cout<<"2 DeleteChild()"<<endl; cout<<"3 PreOrderTraverse()"<<endl; cout<<"4 InOrderTraverse()"<<endl; cout<<"5 PostOrderTraverse()"<<endl; cout<<"6 Parent()"<<endl; cout<<"7 LeftChild()"<<endl; cout<<"8 RightChild()"<<endl; cout<<"9 leftSibling()"<<endl; cout<<"10 RightSibling()"<<endl; cout<<"11 Root()"<<endl; cout<<"12 Value()"<<endl; cout<<"13 Assign()"<<endl; cout<<"--------------------------------------"<<endl; ll1:cout<<"請輸入您選擇的函數序號:)"<<endl; int number; cin>>number; SqBiTree bt; initBiTree(bt); createBiTree(bt);//創建一個可以公用的二叉樹bt Elemtype e;position p; switch(number){ case 1: SqBiTree c; initBiTree(c); createBiTree(c); InsertChild(bt,3,1,c); print(bt); break; case 2: DeleteChild(bt,3,1); print(bt); break; case 3: PreOrderTraverse(bt); break; case 4: InOrderTraverse(bt); break; case 5: PostOrderTraverse(bt); break; case 6: cout<<"輸入E的值"<<endl; cin>>e; cout<<Parent(bt,e); break; case 7: cout<<"輸入E的值"<<endl; cin>>e; cout<<LeftChild(bt,e); break; case 8: cout<<"輸入E的值"<<endl; cin>>e; cout<<RightChild(bt,e); break; case 9: cout<<"輸入E的值"<<endl; cin>>e; cout<<LeftSibling(bt,e); break; case 10: cout<<"輸入E的值"<<endl; cin>>e; cout<<RightSibling(bt,e); break; case 11: cout<<Root(bt); break; case 12: cout<<"請輸入P的位置(level,order)"<<endl; int a,b; cin>>a>>b; initPosition(p,a,b); Value(bt,e,p); cout<<e<<endl; break; case 13: cout<<"請輸入P的位置(level,order)和E的值"<<endl; cin>>a>>b>>e; initPosition(p,a,b); Assign(bt,p,e); print(bt); break; } cout<<"您是否想要繼續調用函數?yes/no"<<endl; string s;cin>>s; if (!s.compare("yes")) goto ll1; else return 0; }
鏈式二叉樹
1.實驗內容
1.輸入字符序列,建立二叉鏈表。 1
2.中序遍歷二叉樹:遞歸算法。3
3.中序遍歷二叉樹:非遞歸算法。(最好也能實現先序,后序非遞歸算法)4
4.求二叉樹的高度 。1
5.求二叉樹的葉子個數。1
*6.將二叉鏈表視為森林的孩子兄弟鏈表,計算森林中葉子個數。1
*7.建立中序線索二叉樹,並實現中序遍歷。1
8.借助隊列實現二叉樹的層次遍歷。1
9.在主函數中設計一個簡單的菜單,分別調試上述算法。1
*10.綜合訓練:為N個權值設計哈夫曼編碼。
#include <iostream> #include <stdlib.h> #include <stdio.h> #include <string> #include <string.h> #include <math.h> #define MAXSIZE 10 //鏈式二叉樹 using namespace std; typedef char Elemtype; typedef struct BiTNode{ Elemtype data; struct BiTNode *left,*right; }BiTNode,*BiTree; void InitBiTree(BiTree &bt) { bt=NULL;//構造空的二叉樹 } void CreateBiTree(BiTree &bt) { Elemtype e; scanf("%c",&e); if (e==' ') { bt=NULL;//如果輸入空格則將該結點置空 } else { bt=(BiTree)malloc(sizeof(BiTNode)); bt->data=e; CreateBiTree(bt->left); CreateBiTree(bt->right); } } void PreOrderTraverse(BiTree &bt) { if (bt!=NULL) { printf("%c",bt->data); PreOrderTraverse(bt->left); PreOrderTraverse(bt->right); } } void InOrderTraverse(BiTree &bt) { if (bt)//如果是空則不用遍歷左右子樹,如果不空則遍歷 { InOrderTraverse(bt->left); printf("%c",bt->data); InOrderTraverse(bt->right); } } void PostOrderTraverse(BiTree &bt ) { if (bt) { PostOrderTraverse(bt->left); PostOrderTraverse(bt->right); printf("%c",bt->data); } } void LevelOrderTraverse(BiTree &bt) { BiTree q[MAXSIZE];//指針數組 int front,rear; //初始化隊列 front=rear=-1; if (bt) { rear=(rear+1)%MAXSIZE; q[rear]=bt;//安置根節點 //不斷循環,直到隊空為止 while (front!=rear) { //如果隊不空,隊頭出隊 front=(front+1)%MAXSIZE; printf("%c",q[front]->data); //左右孩子不空則入隊 if (q[front]->left) { rear=(rear+1)%MAXSIZE; q[rear]=q[front]->left;//安置根節點 } if (q[front]->right) { rear=(rear+1)%MAXSIZE; q[rear]=q[front]->right;//安置根節點 } } } } int BiTreeEmpty(BiTree &bt) { if (!bt) return 1; } int BiTreeDepth(BiTree &bt) { int depth=0; int depthL,depthR; if (!bt) depth=0; else { depthL=BiTreeDepth(bt->left); depthR=BiTreeDepth(bt->right); depth=1+(depthL>depthR?depthL:depthR); } return depth; } Elemtype Root (BiTree &bt) { if (bt) { return bt->data; } else return 0; } Elemtype Value(BiTree &p) { //P是二叉樹中某個節點 return p->data; } void Assign(BiTree &bt,Elemtype e) { bt->data=e; } Elemtype Parent(BiTree &bt,Elemtype e) { //e為二叉樹bt中的某個節點,輸出他的雙親 BiTree q[MAXSIZE],p; int rear,front; rear=front =-1 ; if (bt) { rear=(rear+1)%MAXSIZE; q[rear]=bt;//根節點入隊 while (rear!=front) { //如果隊不空則隊頭出隊 front=(front+1)%MAXSIZE; p=q[front]; if (p && p->left->data ==e || p && p->right->data == e ) { //如果P本身不空並且有一個孩子等於E,則返回該雙親節點的值 return p->data; } //說明這次沒有找到和E相等的節點,則把左孩子和右孩子送入隊列 if (p->left) { rear=(rear+1)%MAXSIZE; q[rear]=p->left; } if (p->right) { rear=(rear+1)%MAXSIZE; q[rear]=p->right; } } } } BiTree findE(BiTree &bt,Elemtype e) { BiTree q[MAXSIZE],p; int rear,front; rear=front=-1; if (bt) { rear=(rear+1)%MAXSIZE; q[rear]=bt;//根入隊 while (front!=rear) { front=(front+1)%MAXSIZE; p=q[front];//取出隊頭元素 if (p->data == e) { return p; } if (p->left) { rear=(rear+1)%MAXSIZE; q[rear]=p->left;//left child enqueue } if (p->right) { rear=(rear+1)%MAXSIZE; q[rear]=p->right;//left child enqueue } } } } Elemtype LeftChild( BiTree &bt,Elemtype e) { //找到指向E的指針 BiTree p=findE(bt,e); if (p &&p->left ) {//P不為空並且左孩子不為空 return p->left->data; } else return 0; } Elemtype RightChild( BiTree &bt,Elemtype e) { //找到指向E的指針 BiTree p=findE(bt,e); if (p &&p->right ) {//P不為空並且左孩子不為空 return p->right->data; } else return 0; } BiTree findP(BiTree &bt,Elemtype e) { //e為二叉樹bt中的某個節點,輸出他的雙親 BiTree q[MAXSIZE],p; int rear,front; rear=front =-1 ; if (bt) { rear=(rear+1)%MAXSIZE; q[rear]=bt;//根節點入隊 while (rear!=front) { //如果隊不空則隊頭出隊 front=(front+1)%MAXSIZE; p=q[front]; if (p && p->left->data ==e || p && p->right->data == e ) { //如果P本身不空並且有一個孩子等於E,則返回該雙親節點的值 return p; } //說明這次沒有找到和E相等的節點,則把左孩子和右孩子送入隊列 if (p->left) { rear=(rear+1)%MAXSIZE; q[rear]=p->left; } if (p->right) { rear=(rear+1)%MAXSIZE; q[rear]=p->right; } } } } Elemtype LeftSibling(BiTree &bt,Elemtype e) { BiTree parent = findP(bt,e);//找到E元素的雙親指針 if (parent->left) { return parent->left->data; } } Elemtype RightSibling(BiTree &bt,Elemtype e) { BiTree parent = findP(bt,e);//找到E元素的雙親指針 if (parent->right) { return parent->right->data; } } int InsertChild(BiTree &p ,int lr,BiTree &c) {//插入更簡單了!! if (p) { if (lr==0)//把C移到P的左子樹上 { c->right=p->left; p->left=c; }else { c->right=p->right; p->right=c; } return 1; } else return 0;//P為空 } void clearBiTree(BiTree &bt) { //同樣用遞歸! if (bt) { if (bt->left) clearBiTree(bt->left); if (bt->right) clearBiTree(bt->right); free(bt); bt=NULL; } } void DeleteChild(BiTree &p,int LR) { // 初始條件: 二叉樹T存在,p指向T中某個結點,LR為0或1 // 操作結果: 根據LR為0或1,刪除T中p所指結點的左或右子樹 if (p) { if (LR == 1) { clearBiTree(p->left); }else { clearBiTree(p->right); } } } //非遞歸實現pre/in/post 遍歷二叉樹 //使用棧實現中序遍歷 typedef BiTree Elemtype1; typedef struct { Elemtype1 elem[MAXSIZE]; int top; }SeqStack; void initSeqStack(SeqStack &s){ s.top=-1; } int stackEmpty(SeqStack &s){ if (s.top==-1) return 1; return 0;//或者返回 表達式的真值return s.top==-1; } int push(SeqStack &s,Elemtype1 e){ if (s.top>=MAXSIZE-1) return 0; else { s.top++; s.elem[s.top]=e; return 1; } } int pop(SeqStack &s,Elemtype1 &e){ if (s.top==-1) return 0; else { e=s.elem[s.top]; s.top--; return 1; } } int gettop(SeqStack &s,Elemtype1 &e){ if (s.top==-1) return 0; else { e=s.elem[s.top]; return 1; } } //中序遍歷非遞歸算法 void InOrderTraverse2(BiTree &bt) { //精髓是把每個結點的地址存入棧中,通過push & pop實現過程 SeqStack s; initSeqStack(s); BiTree p=bt; while (p!=NULL || !stackEmpty(s)) { //當且僅當兩者都空時結束循環 if (p) { push(s,p); p=p->left; } else { pop(s,p);//彈回根節點 printf("%c ",p->data);//第二次回到根節點時才打印輸出 p=p->right; } } } //先序遍歷非遞歸算法 void PreOrderTraverse2(BiTree p) { //這里不加&即為形參,便不用定義新的變量作為移動的指針了 SeqStack s; initSeqStack(s); do { if (p) { printf("%c ",p->data); push(s,p); p=p->left; } else { pop(s,p); p=p->right; } }while (p || !stackEmpty(s)); } //后序遍歷非遞歸算法 void PostOrderTraverse2(BiTree p) { struct { BiTree pp;//pointer int tag;//標記位 }s[MAXSIZE];//定義一個結構體數組,即為一個棧s //這里struct之前不能加typedef ,因為s[]是結構體數組而不是別名 int top=0;//棧頂指針 while ( p || top>0) { while (p)//一直走到最左邊 { top++; s[top].pp=p; s[top].tag=0; p=p->left; } if (top>0) { if (s[top].tag == 0) { //如果棧頂元素標志位為0,即為第二次遇到該結點元素 s[top].tag=1; p=s[top].pp; p=p->right;//繼續向右孩子深入 } else { p=s[top].pp; printf("%c ",p->data);//如果是第二次遇到該節點則輸出 top--; p=NULL;//不用往深處走了,直接退棧繼續循環 } } } } //找到葉子結點個數,左右孩子都空 int findleaf(BiTree p,int &count1) { if (p) { if ( !p->left &&!p->right) count1++; findleaf(p->left,count1); findleaf(p->right,count1); } } int findrightleaf(BiTree p,int &count1) { if (p) { if (!p->right) count1++; findleaf(p->left,count1); findleaf(p->right,count1); } } void PreOrderfindall(BiTree &bt,int &count2) { if (bt!=NULL) { count2++; PreOrderfindall(bt->left,count2); PreOrderfindall(bt->right,count2); } } int findleafinforest(BiTree &bt) { //假設bt代表一個森林,求森林中葉子的個數 //利用理論:假設森林中有N個非終端結點,則二叉樹中右指針域為空的結點個數為N+1 if (bt) { int count1 = 0; findrightleaf(bt,count1); //count即為二叉樹中右指針域為空的結點的個數 int count2=0; PreOrderfindall(bt,count2); //count2即為二叉樹中所有節點的個數,也就是森林總結點個數 return (count2-count1+1); } else return 0; } //建立中序線索二叉樹並遍歷 typedef enum PointerTag {link=0,thread=1};//link=0 指針,thread=1 線索 typedef struct BithrNode{ Elemtype data; struct BithrNode *left,*right; PointerTag ltag,rtag; }BithrNode,*BithrTree; int InOrderThreading(BithrTree &thrt,BithrTree bt) { void Inthreading(BithrTree &p,BithrTree &pre); //將普通二叉樹線索化成thrt //1.建立頭結點 thrt = (BithrTree)malloc(sizeof(BithrNode)); BithrTree pre; thrt->right=thrt; thrt->ltag=link; thrt->rtag=thread; if (!bt) thrt->left=thrt; else { thrt->left = bt; pre=thrt;//前驅指針指向頭結點 Inthreading(bt,pre); //線索化二叉樹 pre->right=thrt; pre->rtag=thread; thrt->right=pre; //線索化最后pre指向樹中最后一個結點,進行最后的處理:連接樹中最后一個結點與頭結點,形成循環的線索樹 } } void Inthreading(BithrTree &p,BithrTree &pre) { if (p) { Inthreading(p->left,pre); if (!p->left)//P的左孩子為空 { p->ltag=thread; p->left=pre; } if (!pre->right)//Pre的右孩子為空 { pre->rtag=thread; pre->right=p; } pre=p; Inthreading(p->right,pre); } } //遍歷線索二叉樹 int InOrderTraverseThrtree(BithrTree &thrt) { BithrTree p=thrt->left; while (p != thrt) { //線索樹不為空時 while(p && p->ltag !=thread) { p=p->left; } printf("%c",p->data); while(p->rtag == thread && p->right != thrt) { //如果p->right==T,則不用繼續往右走 p=p->right; printf("%c",p->data); } p=p->right;//沒有右線索,只有右孩子 } } void CreateBithrTree(BithrTree &bt) { Elemtype e; scanf("%c",&e); if (e==' ') { bt=NULL;//如果輸入空格則將該結點置空 } else { bt=(BithrTree)malloc(sizeof(BithrNode)); bt->data=e; CreateBithrTree(bt->left); CreateBithrTree(bt->right); } } int main() { cout<<"---二叉樹的基本操作實現 twomeng---"<<endl; cout<<"--------------------------------------"<<endl; cout<<"1 InsertChild()"<<endl; cout<<"2 DeleteChild()"<<endl; cout<<"3 PreOrderTraverse()"<<endl; cout<<"4 InOrderTraverse()"<<endl; cout<<"5 PostOrderTraverse()"<<endl; cout<<"6 Parent()"<<endl; cout<<"7 LeftChild()"<<endl; cout<<"8 RightChild()"<<endl; cout<<"9 leftSibling()"<<endl; cout<<"10 RightSibling()"<<endl; cout<<"11 Root()"<<endl; cout<<"12 Value()"<<endl; cout<<"13 Assign()"<<endl; cout<<"14 LevelOrderTraverse()"<<endl; cout<<"15 BiTreeDepth()"<<endl; cout<<"16 findleaf()"<<endl; cout<<"17 PreOrderTraverse2()"<<endl; cout<<"18 InOrderTraverse2()"<<endl; cout<<"19 PostOrderTraverse2()"<<endl; cout<<"20 findleafinforest()"<<endl; cout<<"21 線索化二叉樹並中序遍歷輸出"<<endl; cout<<"--------------------------------------"<<endl; ll1:cout<<"請輸入您選擇的函數序號:)"<<endl; int number; cin>>number; BiTree bt,p; InitBiTree(bt); Elemtype e;int count3 = 0; cout<<"請按照先序順序輸入一棵樹!沒有結點的地方請輸入空格"<<endl; fflush(stdin); CreateBiTree(bt);//創建一個可以公用的二叉樹bt; switch(number) { case 1: PreOrderTraverse(bt); BiTree c; InitBiTree(c); cout<<"請按照先序順序輸入一棵Insert樹!沒有結點的地方請輸入空格"<<endl; fflush(stdin); CreateBiTree(c); LevelOrderTraverse(c); cout<<"輸入完畢!"<<endl; cout<<"如果您想插入到左子樹,輸入0;如果您想插入到右子樹,輸入1 "<<endl; int x;cin>>x; InsertChild(bt,x,c); PreOrderTraverse(bt); break; case 2: PreOrderTraverse(bt); cout<<endl; cout<<"刪除左子樹,請輸入1;刪除右子樹,請輸入0"<<endl; cin>>x; DeleteChild(bt,x); PreOrderTraverse(bt); break; case 3: PreOrderTraverse(bt); break; case 4: InOrderTraverse(bt); break; case 5: PostOrderTraverse(bt); break; case 6: char ch; cout<<"請輸入您要尋找的節點數值"<<endl; cin>>ch; cout<<Parent(bt,ch); break; case 7: cout<<"輸入E的值"<<endl; cin>>e; cout<<LeftChild(bt,e); break; case 8: cout<<"輸入E的值"<<endl; cin>>e; cout<<RightChild(bt,e); break; case 9: cout<<"輸入E的值"<<endl; cin>>e; cout<<LeftSibling(bt,e); break; case 10: cout<<"輸入E的值"<<endl; cin>>e; cout<<RightSibling(bt,e); break; case 11: cout<<Root(bt); break; case 12: p=bt->left; cout<<Value(p)<<endl; break; case 13: p=bt->left; cout<<"請輸入您要賦的值"<<endl; cin>>e; Assign(p,e); cout<<"assign函數調用成功!其中的值現在為:"<<endl; cout<<p->data<<endl; break; case 14: LevelOrderTraverse(bt); break; case 15: cout<<BiTreeDepth(bt)<<endl; break; case 16: findleaf(bt,count3); cout<<count3<<endl; break; case 17: PreOrderTraverse2(bt); break; case 18: InOrderTraverse2(bt); break; case 19: PostOrderTraverse2(bt); break; case 20: cout<<findleafinforest(bt)<<endl; break; case 21: BithrTree bt; CreateBithrTree(bt); BithrTree thrt; cout<<"線索化二叉樹成功!"<<endl; InOrderThreading(thrt,bt); InOrderTraverseThrtree(thrt); cout<<"遍歷線索二叉樹成功!"<<endl; break; } cout<<"您是否想要繼續調用函數?yes/no"<<endl; string s;cin>>s; if (!s.compare("yes")) goto ll1; else return 0; }
我這個哈夫曼樹貌似有點問題,結果不太對啊。。有空再調一調
哈夫曼測試數據:
8 5 29 7 8 14 23 3 11 未調試出來的哈夫曼:
#include <iostream> #include <stdlib.h> #include <stdio.h> #include <string> #include <string.h> #include <math.h> #define MAXSIZE 20 using namespace std; //哈夫曼編碼 typedef struct { unsigned int weight; unsigned int parent,lchild,rchild; }HTNode,*HuffmanTree; typedef char* *Huffmancode;//定義一個指針數組存放編碼 int min(HuffmanTree t,int i) { // 函數void select()調用 int j,flag; unsigned int k=UINT_MAX; // 取k為不小於可能的值 for(j=1;j<=i;j++) if(t[j].weight<k&&t[j].parent==0) k=t[j].weight,flag=j; t[flag].parent=1; return flag; } void select(HuffmanTree t,int i,int &s1,int &s2) { // s1為最小的兩個值中序號小的那個 int j; s1=min(t,i); s2=min(t,i); if(s1>s2) { j=s1; s1=s2; s2=j; } } void HuffmanCoding(HuffmanTree &ht,Huffmancode &hc,int *w,int n) { int i; if (n<=1) return;//判斷N(字符個數)的輸入是否合法 int m;//哈夫曼樹結點個數 m = 2*n-1; //哈夫曼樹是一個數組,我們要先定義出來, 再初始化數組 ht = (HuffmanTree )malloc((m+1)*sizeof(HTNode));//0 單元未用 //給初始字符賦權值 HuffmanTree p; p=ht; p++; int *t;t=w; for (i=1,t++;i<=n;i++,p++,t++) { (*p).weight=*t; (*p).lchild=0; (*p).rchild=0; (*p).parent=0; } //給還沒計算的結點賦值0 for (p=&ht[n+1],i=n+1;i<=m;i++,p++) { (*p).weight=0; (*p).lchild=0; (*p).rchild=0; (*p).parent=0; } //建立哈夫曼樹 for(int i=n+1;i<=m;i++) { int s1,s2; select(ht,i-1,s1,s2);//最小的兩個結點序號為s1,s2 ht[s1].parent=i; ht[s2].parent=i; ht[i].lchild=s1; ht[i].rchild=s2; ht[i].weight=ht[s1].weight+ht[s2].weight; } //show() // for (i=1 ; i<=m ; i++) // { // cout<< ht[i].weight <<" " <<ht[i].parent <<" "<<ht[i].lchild <<" "<<ht[i].rchild<<endl; // } //進行哈夫曼編碼 int c,f; hc=(Huffmancode)malloc(sizeof(char *)*(n+1));//頭指針向量 char *cd = (char *)malloc(sizeof(char)*n);//一個字符編碼的數組指針 cd[n-1]='\0'; for (int i=1;i<=n;i++)//循環N個字符 { int start = n-1;//從葉節點開始往上編 for (c=i,f=ht[i].parent;f!=0;c=f,f=ht[f].parent) { //定義C是為了不動I,順次往上找雙親,判斷自己是雙親的左子樹還是右子樹 if (ht[f].lchild == c) cd[--start]='0'; else cd[--start]='1'; } for (int x = n-start;x<n;x++) cout<<cd[x]; hc[i]=(char *)malloc((n-start)*sizeof(char)); strcpy(hc[i],cd); //cout<<hc[i]<<endl; } } int main() { int *w,*ww; int n; cout<<"請輸入字符數N"<<endl; cin>>n; w=(int *)malloc(sizeof(int)*(n+1));//0號單元未用 ww=w; int i; cout<<"請依次輸入字符的權值"<<endl; for (ww++,i=1;i<=n;i++,ww++) { cin>> *ww; } HuffmanTree ht; Huffmancode hc; HuffmanCoding(ht,hc,w,n); Huffmancode q=hc; for (int k=1;k<=n;k++) puts(hc[k]); return 0; }