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; }
时间: 2024-10-26 19:26:27