二叉樹的基本操作C++
阿新 • • 發佈:2019-01-02
二叉樹實現
1.建立二叉樹
2.遞迴輸出二叉樹
2.1遞迴先序輸出
2.2遞迴中序輸出
2.3遞迴後序輸出
3.非遞迴輸出
3.1非遞迴先序輸出
3.2非遞迴中序輸出
3.3非遞迴後序輸出
4.層次遍歷二叉樹
5.求樹高
6.求樹葉子節點
7.按值查詢對應節點,輸出左孩子結點值和右孩子結點值
1.建立二叉樹
2.遞迴輸出二叉樹
2.1遞迴先序輸出
2.2遞迴中序輸出
2.3遞迴後序輸出
3.非遞迴輸出
3.1非遞迴先序輸出
3.2非遞迴中序輸出
3.3非遞迴後序輸出
4.層次遍歷二叉樹
5.求樹高
6.求樹葉子節點
7.按值查詢對應節點,輸出左孩子結點值和右孩子結點值
8.計算所有節點數
測試結果/* 二叉樹實現 1.建立二叉樹 2.遞迴輸出二叉樹 2.1遞迴先序輸出 2.2遞迴中序輸出 2.3遞迴後序輸出 3.非遞迴輸出 3.1非遞迴先序輸出 3.2非遞迴中序輸出 3.3非遞迴後序輸出 4.層次遍歷二叉樹 5.求樹高 6.求樹葉子節點 7.按值查詢對應節點,輸出左孩子結點值和右孩子結點值 8.計算所有節點數 */ #include<iostream> #include<string> #include<stack> #include<deque> #include<fstream> using namespace std; //const int MAX_N = 100; //資料節點 class Node { public: char data;//資料 class Node *lchild;//左節點 class Node *rchild;//右節點 }; //二叉樹 class Tree { public: Tree(){} ~Tree(){} //構建二叉樹 void Create(string name) { ifstream readfile; string str; readfile.open(name); if (readfile.is_open()) { getline(readfile, str);//讀取一行 } readfile.close(); CreateNode(str);//構建二叉樹 } //先序遍歷非遞迴演算法 void Disp() { if (t == NULL) { return; } stack<Node *> m_stack;//定義棧 m_stack.push(t); while (!m_stack.empty()) { Node *p = m_stack.top();//賦值一份當前雙親節點 cout << p->data << ends; m_stack.pop(); if (p->rchild)//先儲存右子樹,確保先輸出左子樹 { m_stack.push(p->rchild); } if (p->lchild)//後儲存左子樹 { m_stack.push(p->lchild); } } } //非遞迴中序遍歷二叉樹 void DispMid() { if (t == NULL) { return; } Node *p = t; stack<Node *>m_stack; while (p != NULL || !m_stack.empty()) { while (p != NULL)//一路直走至左下角 { m_stack.push(p); p = p->lchild; } if (!m_stack.empty()) { p = m_stack.top();//備份當前棧頂地址 m_stack.pop(); cout << p->data << ends; p = p->rchild; } } } //非遞迴後序遍歷二叉樹 void DispBehid() { if (t == NULL) { return; } Node *pre = NULL, *p = t; stack<Node *>m_stack; while (p != NULL || !m_stack.empty()) { while (p != NULL)//一路直走至左下角 { m_stack.push(p); p = p->lchild; } p = m_stack.top(); //右子樹為空或者已訪問,輸出當前節點 if (p->rchild == NULL || p->rchild == pre) { cout << p->data << ends; pre = p;//將當前結點地址賦值pre作為下一次判斷標誌,防止重複訪問 m_stack.pop(); p = NULL;//p賦值空以便訪問右子樹 } else { p = p->rchild;//訪問子樹的右子樹 } } } //層次遍歷 void level_display() { if (t == NULL) { return; } deque<Node *>m_qu;//定義佇列 m_qu.push_back(t);//樹根入佇列 while (!m_qu.empty()) { Node *p = m_qu.front();//拷貝當前對頭 cout <<p->data << ends;//輸出 m_qu.pop_front(); if (p->lchild)//左孩子入佇列 { m_qu.push_back(p->lchild); } if (p->rchild)//右孩子入佇列 { m_qu.push_back(p->rchild); } } } //遞迴先序遍歷輸出二叉樹 void display() { cout << "遞迴先序:"; output(t); cout << endl; } //遞迴中序遍歷輸出二叉樹 void displayMid() { cout << "遞迴中序:"; outputMid(t); cout << endl; } //遞迴後序遍歷輸出二叉樹 void displayBhind() { cout << "遞迴後序"; outputBhind(t); cout << endl; } //二叉樹高度 void Height() { int height = get_height(t); cout << "Height: " << height << endl; } //輸出葉子節點值 void display_leaf() { cout << "Leaves: "; output_leaf(t); cout << endl; } //查詢二叉樹中值data域為elem的節點 void find_node(char elem) { Node *res = NULL; res = find_node(t, elem, res); if (res != NULL) { cout << "nice." << endl; if (res->lchild) { cout << "left child:"; cout << leftchild(res)->data << endl; } if (res->rchild) { cout << "right child:"; cout << rightchild(res)->data << endl; } } else { cout << "NO." << endl; } } //計算節點數 void nodes_count() { int sum; if (t == NULL)//若為空,則0個節點 { sum = 0; } else { sum = node_count(t); cout << "Total Nodes:" << sum + 1 << endl; } } private: Node *t; //構建二叉樹 void CreateNode(string str) { stack<Node *> m_stack; Node *p; int k; while (str.length() != 0) { //若當前為'(',將雙親節點推入棧,下一位儲存的p值作為左節點處理 if (str[0] == '(') { m_stack.push(p); k = 1; } //為右括號則棧頂退出一位 else if (str[0] == ')') { m_stack.pop(); } //為',',則下一個字元作右節點處理 else if (str[0] == ',') { k = 2; } //儲存值用作雙親結點 else { p = (Node *)malloc(sizeof(Node)); p->data = str[0]; p->lchild = p->rchild = NULL; //樹根為空時,將第一個節點作為樹根並賦值給私有成員變數 if (t == NULL) { t = p; } //樹根不為空 else { if (k == 1)//作為左節點處理,將棧中雙親節點的左指標指向當前節點 { m_stack.top()->lchild = p; } else//作為右節點處理 { m_stack.top()->rchild = p; } } } //重構串,除去首字元,並將串長度減小1 str.assign(str.substr(1, str.length() - 1)); } } //遞迴先序遍歷輸出二叉樹 void output(Node *t) { if (t != NULL)//當樹根不為空時 { cout << t->data;//輸出 if (t->lchild != NULL || t->rchild != NULL)//左/右結點不為空時遞迴到下一層 { cout << "("; output(t->lchild); if (t->rchild != NULL)//當左節點遍歷結束後,左節點遞迴返回一層,遞迴右節點 { cout << ","; } output(t->rchild); cout << ")"; } } } //遞迴中序遍歷二叉樹 void outputMid(Node *t) { if (t == NULL)//空則返回 { return; } else { cout << "("; outputMid(t->lchild);//遞迴左孩子節點 if (t->rchild != NULL) { cout << ","; } cout << t->data;//輸出 outputMid(t->rchild);//遞迴右孩子結點 cout << ")"; } } //遞迴後序遍歷輸出二叉樹 void outputBhind(Node *t) { if (!t)//空則返回 { return; } else { cout << "("; outputBhind(t->lchild);//遞迴左孩子節點 if (t->rchild != NULL) { cout << ","; } outputBhind(t->rchild);//遞迴右孩子結點 cout << t->data;//輸出 cout << ")"; } } //求樹高 int get_height(Node *t) { int leftheight, rightheight; if (t == NULL)//遞迴至不存在子節點時返回0 { return 0; } else { leftheight = get_height(t->lchild);//遞迴求左子樹高度 rightheight = get_height(t->rchild);//遞迴其右子樹高度 return leftheight > rightheight ? leftheight+1 : rightheight+1;//遞迴返回時返回最大值 } } //查詢左節點 Node *leftchild(Node *p) { return p->lchild; } //查詢右節點 Node *rightchild(Node *p) { return p->rchild; } //輸出葉子節點 void output_leaf(Node *t) { if (t != NULL)//樹根不為空時 { //當前節點沒有子節點時輸出節點資料 if (t->lchild == NULL&&t->rchild == NULL) { cout << t->data << ends; } output_leaf(t->lchild);//遞迴左子樹 output_leaf(t->rchild);//遞迴右子樹 } } //查詢二叉樹中值data域為elem的節點 Node * find_node(Node *t, char elem, Node *res = NULL) { //Node *res = NULL; if (t == NULL)//若當前節點為空,則返回結束 { return NULL; } else { if (t->data == elem)//若找到值,返回地址 { //res = t; return t; } else { if (res == NULL)//若儲存結果的指標不為空,則遞迴查詢左節點 { res = find_node(t->lchild, elem, res); } if (res == NULL)//若儲存結果的指標不為空,且左節點為搜尋到,則遞迴查詢右節點 { res = find_node(t->rchild, elem, res); } } return res; } } //計算節點數 int node_count(Node *t) { int lcount = 0, rcount = 0; if (t == NULL)//空則返回 { return 0; } else { if (t->lchild != NULL)//遍歷左孩子節點 { lcount = node_count(t->lchild); lcount += 1; } if (t->rchild != NULL)//遍歷右孩子節點 { rcount = node_count(t->rchild); rcount += 1; } return lcount + rcount;//返回當前左右孩子節點數 } } }; int main() { Tree m_tree; m_tree.Create("data"); m_tree.display();//遞迴先序輸出 m_tree.displayMid();//遞迴中序輸出 m_tree.displayBhind();//遞迴後序輸出 m_tree.Height();//樹高 m_tree.display_leaf();//葉子節點 cout << "非遞迴先序:"; //cout << "Fir:"; m_tree.Disp();//非遞迴先序遍歷 cout << endl; cout << "非遞迴中序:"; //cout << "Mid:"; m_tree.DispMid();//非遞迴中序遍歷 cout << endl; cout << "非遞迴後序:"; //cout << "Bac:"; m_tree.DispBehid();//非遞迴後序遍歷 cout << endl; cout << "層次遍歷:"; m_tree.level_display();//層次遍歷 cout << endl; cout << "Input element:"; char elem; cin >> elem; m_tree.find_node(elem);//按節點值查詢 m_tree.nodes_count();//計算節點數 return 0; }