实验二 二叉树的操作与实现
生活随笔
收集整理的這篇文章主要介紹了
实验二 二叉树的操作与实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
記錄實驗,同時也是記錄常見數據結構算法的實現。
廣州大學學生實驗報告
開課實驗室:計算機科學與工程實驗(電子樓416A)
學院 計算機科學與網絡工程學院
實驗課程 數據結構實驗
實驗項目 實驗二 二叉樹的操作與實現
- 一、實驗目的:
1、二叉樹的基本操作算法實現
2、二叉樹的各種遍歷算法實現
3、線索二叉樹的遍歷
4、構造哈夫曼樹和哈夫曼編碼的算法實現 - 二、使用儀器、器材
微機一臺
操作系統:Win10
編程軟件:C++ - 三、實驗內容及原理
1、二叉樹的基本操作算法實現 (返回目錄🖱)
2、二叉樹的各種遍歷算法實現 (返回目錄🖱)
#include <iostream> using namespace std;int leave_counts = 0;//-----二叉樹的二叉鏈表表示----- typedef struct BiTNode {char data;BiTNode* lchild, * rchild; }BiTNode, * BiTree;//-----用棧來實現二叉鏈表的非遞歸----- typedef struct BiTNodeStack {BiTNode* data;BiTNodeStack* next; }BiTNodeStack,*BiTStack; //-----初始化棧----- void InitStack(BiTStack& s) {s = new BiTNodeStack;s->data = NULL;s->next = NULL; } //-----彈出----- BiTNode* Pop(BiTStack s) {BiTNodeStack* p = new BiTNodeStack;p = s->next;s->next = p->next;return p->data; } //-----放入----- void Push(BiTStack &s,BiTNode *p) {BiTNodeStack* sp = new BiTNodeStack;sp->data = p;sp->next = s->next;s->next = sp; }//-----先序遍歷建立二叉樹----- void CreatBiTNode(BiTree& T, const char* str) {BiTNode* ParentTNode[20], * p = NULL;int top = -1, k = 0, j = 0;char ch;T = NULL;ch = str[j];while (ch != '\0'){switch (ch){case'(':top++; ParentTNode[top] = p; k = 1; break;case')':top--; break;case',':k = 2; break;default: p = new BiTNode;p->data = ch;p->lchild = NULL;p->rchild = NULL;if (T == NULL) T = p;switch (k){case 1:ParentTNode[top]->lchild = p; break;case 2:ParentTNode[top]->rchild = p; break;}}j++;ch = str[j];} }//-----遞歸先序遍歷輸出二叉樹----- void ShowBiTree_preorder(BiTree T) {if (T){cout << T->data;ShowBiTree_preorder(T->lchild);ShowBiTree_preorder(T->rchild);} } //-----非遞歸先序遍歷輸出二叉樹----- void ShowBiTree_preorder_0(BiTree T) {BiTNode* p = new BiTNode;p = T;BiTStack s;InitStack(s);while (p || s->next != NULL){while (p){cout << p->data;Push(s, p);p = p->lchild;}if (s->next != NULL){p = Pop(s);p = p->rchild;}} } //-----遞歸中序遍歷輸出二叉樹----- void ShowBiTree_inorder(BiTree T) {if (T){ShowBiTree_inorder(T->lchild);cout << T->data;ShowBiTree_inorder(T->rchild);} } //-----非遞歸中序遍歷輸出二叉樹----- void ShowBiTree_inorder_0(BiTree T) {BiTNode* p = new BiTNode;p = T;BiTStack s ;InitStack(s);while (p || s->next != NULL){if (p){Push(s, p);p = p->lchild;}else{BiTNode* q = new BiTNode;q = Pop(s);cout << q->data;p = q->rchild;}} }//-----遞歸后序遍歷輸出二叉樹----- void ShowBiTree_postorder(BiTree T) {if (T){ShowBiTree_postorder(T->lchild);ShowBiTree_postorder(T->rchild);cout << T->data;} } //-----非遞歸后序遍歷輸出二叉樹----- void ShowBiTree_postorder_0(BiTree T) {BiTNode* p = new BiTNode;p = T;BiTStack s1,s2;InitStack(s1);InitStack(s2);while (p || s1->next != NULL){while (p){Push(s2, p);Push(s1, p);p = p->rchild;}if (s1->next != NULL){p = Pop(s1);p = p->lchild;}}while (s2->next != NULL){p = Pop(s2);cout << p->data;} }int main() {BiTree T = new BiTNode;const char* ch = "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))\0";CreatBiTNode(T, ch);//遞歸先序遍歷輸出cout << "先序遍歷輸出:";ShowBiTree_preorder(T);cout <<" (遞歸)"<<endl;//非遞歸先序遍歷輸出cout << "先序遍歷輸出:";ShowBiTree_preorder_0(T);cout << " (非遞歸)" << endl<<"----------------"<<endl;//遞歸中序遍歷輸出cout << "中序遍歷輸出:";ShowBiTree_inorder(T);cout << " (遞歸)" << endl;//非遞歸中序遍歷輸出cout << "中序遍歷輸出:";ShowBiTree_inorder_0(T);cout << " (非遞歸)" << endl << "----------------" << endl;//遞歸后序遍歷輸出cout << "后序遍歷輸出:";ShowBiTree_postorder(T);cout << " (遞歸)" << endl;//非遞歸后序遍歷輸出cout << "后序遍歷輸出:";ShowBiTree_postorder_0(T);cout << " (非遞歸)" << endl;}3、線索二叉樹的遍歷 (返回目錄🖱)
#include<iostream> using namespace std;//-----線索二叉樹----- typedef struct BiThrNode {char data;BiThrNode* lchild, * rchild;int LTag, RTag; }BiThrNode,*BiThrTree;BiThrNode* pre = new BiThrNode; // 全局變量pre //-----先序遍歷建立二叉樹----- void CreatBiTNode(BiThrTree& T, const char* str) {BiThrNode* ParentTNode[20], * p = NULL;int top = -1, k = 0, j = 0;char ch;T = NULL;ch = str[j];while (ch != '\0'){switch (ch){case'(':top++; ParentTNode[top] = p; k = 1; break;case')':top--; break;case',':k = 2; break;default: p = new BiThrNode;p->data = ch;p->lchild = NULL;p->rchild = NULL;if (T == NULL) T = p;switch (k){case 1:ParentTNode[top]->lchild = p; break;case 2:ParentTNode[top]->rchild = p; break;}}j++;ch = str[j];} }//-----中序線索化二叉樹----- void InThreading(BiThrTree p) {pre->LTag = 0;pre->RTag = 0;pre->rchild = NULL;if (p){InThreading(p->lchild);if (!p->lchild){p->LTag = 1;p->lchild = pre;}else p->LTag = 0;if (!pre->rchild){pre->RTag = 1;pre->rchild = p;}else pre->RTag = 0;pre = p;InThreading(p->rchild);} }//-----帶頭結點的二叉樹中序線索化----- void InOrderThreading(BiThrTree& Thrt, BiThrTree T) {Thrt = new BiThrNode;Thrt->LTag = 0;Thrt->RTag = 1;Thrt->rchild = Thrt;if (!T) Thrt->lchild = Thrt;else{Thrt->lchild = T; pre = Thrt;InThreading(T);pre->rchild = Thrt;pre->RTag = 1;Thrt->rchild = pre;} }//-----先序遍歷輸出二叉樹----- void ShowBiTree(BiThrTree T) {if (T){cout << T->data;ShowBiTree(T->lchild);ShowBiTree(T->rchild);} }int main() {BiThrTree T = new BiThrNode;const char* ch = "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))";//先序遍歷構造二叉樹CreatBiTNode(T, ch);//二叉樹中序線索化BiThrTree Thrt = new BiThrNode;InOrderThreading(Thrt, T);//輸出根節點的前驅和后繼/*中序線索化時引入了頭結點,所以根節點的前驅即為頭結點*/cout << "根結點的前驅:" << Thrt << "(Thrt)"<<endl;cout << "根結點的后繼:" << Thrt->lchild->rchild->data;}4、構造哈夫曼樹和哈夫曼編碼的算法實現(返回目錄🖱)
#include"stdio.h" #include"string.h" #include"malloc.h" #include"iostream" using namespace std; typedef struct HTNode {unsigned int weight;unsigned int parent, lchild, rchild; }HTNode, * HuffTree; typedef char** HuffCode;//------選擇權值最小的兩個結點的下標----- void Select(HuffTree& Ht, int m, int& S1, int& S2) {S1 = 0;S2 = 0;for (int j = 1; j <= m; j++){if (Ht[j].parent == 0 && Ht[j].weight != 0){if (Ht[j].weight < Ht[S1].weight)S1 = j;}}for (int j = 1; j <= m; j++){if (Ht[j].parent == 0 && j != S1 && Ht[j].weight != 0){if (Ht[j].weight < Ht[S2].weight)S2 = j;}}cout <<S1 << " " << S2 << endl;; }//-----哈夫曼編碼函數----- void HuffmanCoding(HuffTree& Ht, HuffCode& Hc, int n, char text[]) { if (n <= 1)return;int m, i, s1, s2;HuffTree p;m = 2 * n - 1;Ht = (HuffTree)malloc((m + 1) * sizeof(HTNode));for (p = Ht + 1, i = 1; i <= m; ++i, ++p) { //初始化哈夫曼樹各個值 p->weight = 0;p->parent = 0;p->lchild = 0;p->rchild = 0;}//讀入一段文本 for (int i = 0; text[i] != '\0'; i++) {Ht[text[i] - 'a' + 1].weight++; //當文本還沒有結束時,統計各個字符的權值 }//構建哈夫曼樹for (i = n + 1; i <= m; ++i) { Select(Ht, i - 1, 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;}// -------從葉子到根逆向求每個字符的哈夫曼編碼------Hc = (HuffCode)malloc((n + 1) * sizeof(char*)); //貌似不能用new,所以使用c語言的動態申請char* cd = (char*)malloc((n) * sizeof(char));cd[n - 1] = '\0'; //編碼結束符 int start;for (i = 1; i <= n; ++i) {start = n - 1;int parent = 0; //暫存父節點下標int c = 0;for (c = i, parent = Ht[i].parent; parent != 0; c = parent, parent = Ht[parent].parent){if (Ht[parent].lchild == c)cd[--start] = '0';else cd[--start] = '1';}//cd[n-1]='\0';Hc[i] = new char[26];//動態申請某字母哈夫曼編碼的空間strcpy(Hc[i], &cd[start]);}free(cd);}//------輸出哈夫曼編碼------ void show(HuffCode& Hc, int n) {cout << "\n輸出哈夫曼編碼:\n"; for (int i = 1; i <= n; i++){cout <<char(i-1+'a')<<":"<< Hc[i];cout << "\n";}} int main() {HuffTree ht;HuffCode hc;int n;char text[] = "The Chinese official said he viewed the TrumpPresidency not as an aberration but as the product of a failing political system. This jibes with other accounts. The Chinese leadership believes that the United States, and Western democracies in general, haven’t risen to the challenge of a globalized economy, which necessitates big changes in production patterns, as well as major upgrades in education and public infrastructure. In Trump and Trumpism, the Chinese see an inevitable backlash to this failure";char* text_transform = strlwr(text); //全部轉化為小寫 HuffmanCoding(ht, hc, 26, text_transform);show(hc, 26); }四、實驗過程原始數據記錄
1、二叉樹的基本操作算法實現
2、二叉樹的各種遍歷算法實現
3、線索二叉樹的遍歷
4、構造哈夫曼樹和哈夫曼編碼的算法實現
五、實驗結果及分析
在二叉樹的操作當中,有許多步驟的思路是一樣的,所以遞歸在二叉樹中的使用會更加廣泛。我覺得遞歸的思想能在二叉樹的操作中得到很好的鍛煉。二叉樹在數據壓縮等方面以其的特性而廣泛被應用,所以我覺得掌握二叉樹在某些實際應用中的實現方法也是特別重要的。
總結
以上是生活随笔為你收集整理的实验二 二叉树的操作与实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2016年《大数据》杂志调查问卷
- 下一篇: 区块链在智慧农业中的应用展望