1. 程式人生 > >二叉樹操作復習

二叉樹操作復習

logs current date 只有一個 sta 符號 end truct root

2017-08-29 11:46:37

writer:pprp

已經寫了二叉樹好幾次了,但是還是有很多細節沒有考慮完全

還有好多東西都沒有考慮到,以後還是要寫這個代碼,把應該考慮的細節都考慮清楚

代碼及講解如下:(都測試過了,應該沒問題,如果有問題請留言)

/*
@theme:樹的建立和遍歷
@writer:pprp
@start:10:00
@end:11:47
@declare:我建立的這個樹好像跟教科書上的樹方向反了一下,
但是不影響理解,教科書上的是大的在右邊,小的在左邊,我的恰好反了過來
@date:2017/8/28
*/

#include <bits/stdc++.h>

using namespace
std; struct tree { int val; tree * l; tree * r; }; //function 1 insert //插入操作,比根節點大的要在左子樹,比根節點小的要放在右子樹 //test:ok tree * Insert(tree *root, int val) { tree * parent; tree * current; tree * newVal = new tree(); newVal->val = val; newVal->r = NULL; newVal->l = NULL;
if(root == NULL) { root = newVal; } else { current = root; while(current != NULL) { parent = current; if(current->val < val)//這裏的符號要與下邊的符號一致 { current = current->l; } else
{ current = current->r; } } if(parent->val < val) //這裏的符號要跟上邊的符號一致 { parent->l = newVal; } else { parent->r = newVal; } } return root; } //function 2: MakeEmpty //test: ok tree* MakeEmpty(tree * root) { if(root != NULL) { MakeEmpty(root->r); MakeEmpty(root->l); delete root; root = NULL; } return NULL; } //function 3: Find value //test:ok //@param:返回一個指針,代表找到該節點的指針,否則返回NULL tree* FindValue(tree * root,int val) { if(root == NULL) return NULL; if(val < root->val) return FindValue(root->r,val); else if(val > root->val) return FindValue(root->l,val); else return root; } //function 4:Find Min //由於樹的構造是有大小之分的所以找小的直接向有子樹找就好 //test:ok tree* FindMin(tree * root) { if(root == NULL) return NULL; else if(root->r == NULL) return root; else return FindMin(root->r); } //function 5: Find Max //直接向右子樹查找就好了 //test:ok tree * FindMax(tree * root) { if(root == NULL) return NULL; else if(root->l == NULL) return root; else return FindMax(root->l); } ////function 6: delete ////test:error ////錯誤原因:思路不大對,如果只有一個子節點的情況,還需要判斷這個本身是左邊子節點還是右邊子節點 //tree * Delete(tree * root, int val) //{ // tree * current = FindValue(root, val); // tree * tmp = NULL; // if(current->l == NULL && current->r == NULL) //如果兩個孩子都沒有就可以直接刪除掉 // { // delete(current); // } // else if(current != NULL) //只有左孩子,將左孩子中最小的值變成原先節點 // { // tmp = FindMin(current); // current->val = tmp->val; // delete(tmp); // tmp = NULL; // } // else if(current->r != NULL) //只有右孩子 // { // tmp = FindMax(current); // current->val = tmp->val; // delete(tmp); // tmp = NULL; // } // else //兩個孩子都有 // { // tmp = FindMin(current); // current->val = tmp->val; // delete(tmp); // tmp = NULL; // } //} //function 6: delete //test:ok //要刪除的節點值為val,最後返回已經修改過的頭結點 tree * Delete(tree * root, int val) { tree * par; tree * kid; //第一部分找到該節點並找到該節點的父親節點 kid = root; while(kid != NULL) { if(kid->val > val) { par = kid; kid = kid->r; } else if(kid->val < val) { par = kid; kid = kid->l; } else if(kid->val == val) { break; //這時候kid指向的是要找的節點 par記錄的是要找的節點的父親節點 } } //沒有找到的情況 if(kid == NULL) { cout << "not find! " << endl; return NULL; } //現在開始判斷是那種情況 //1、如果是都是為空的情況 if(kid->l == NULL && kid->r == NULL) { if(kid == root) //沒有想到,如果是根節點,那麽就直接賦值根節點為空 root = NULL; if(par->l == kid) par->l = NULL; if(par->r == kid) par->r = NULL; delete(kid); }//2、只有一個節點的情況 else if(kid->l == NULL || kid->r == NULL) { if(kid == root) { if(kid->r == NULL) root = kid->l; else root = kid->r; delete(root); } else //分情況討論 { if(par->r == kid && kid->l) { par->r = kid->l; } else if(par->r == kid && kid->r) { par->r = kid->r; } else if(par->l == kid && kid->l) { par->l = kid->l; } else if(par->l == kid && kid->r) { par->l = kid->r; } delete(kid); } } //3、有兩個子節點的情況,這裏采用將左邊最小的替換找到節點的方案 else { tree * tmp = FindMin(kid); kid->val = tmp->val; delete(tmp); } return root; } //前序遍歷輸出 -- ok void preOut(tree * root) { if(root != NULL) { cout << root->val <<" "; preOut(root->l); preOut(root->r); } } //中序遍歷輸出--ok void midOut(tree * root) { if(root != NULL) { midOut(root->l); cout << root->val << " "; midOut(root->r); } } //後序遍歷輸出--ok void backOut(tree * root) { if(root != NULL) { backOut(root->l); backOut(root->r); cout << root->val << " "; } } int main() { int n; cin >> n; int a[100]; tree * root = NULL; for(int i = 0 ; i < n ; i++) { srand((int)time(NULL)+i); a[i] = rand()%100; } for(int i = 0 ; i < n ; i++) cout << a[i] <<" "; cout << endl; //create a tree for(int i = 0 ; i < n ; i++) { root = Insert(root, a[i]); } cout << "preOut:" << endl; preOut(root); cout << endl; // root = MakeEmpty(root); // cout << "preOut:" << endl; // backOut(root); // cout << endl; // int val; // cin >> val; // tree * tmp = FindValue(root,val); // if(tmp != NULL) // cout << tmp->val << endl; tree * tmp = FindMax(root); if(tmp != NULL) cout << tmp->val << endl; tmp = FindMin(root); if(tmp != NULL) cout << tmp->val << endl; cout << "-----" << endl; int val; cin >> val; root = Delete(root,val); cout << "preOut:" << endl; preOut(root); cout << endl; return 0; }

二叉樹操作復習