部分引用部落格:http://blog.csdn.net/mishifangxiangdefeng/article/details/7903794
部分為個人觀點。
寫在前邊:本來知道debug很強大,今天晚上才發現,debug原來可以發現這麼多疏漏的地方,用好debug確實可以事半功倍。
參考答案:
a)需要改變的結點包括“從根結點開始,到要插入到刪除的結點”的這條路徑上的所有結點。
b)首先毫無疑問,需要在persistent_tree_insert函數內建立立一棵新樹,管理三個指標y(跟蹤父結點),x(跟蹤原子結點),x1(跟蹤新子結點)子結點是相對y而言的,思路也比較簡單,在插入的過程中,將途中所有的結點都複製一遍,再修改指標就完成了。
#include<iostream>using namespace std;struct node{int key;node* left;node* right;node* p;node(){}node(int k):key(k),left(NULL),right(NULL),p(NULL){}node(node* cp):key(cp->key),left(cp->left),right(cp->right),p(cp->p){}};struct tree{node* root;tree():root(NULL){}};void tree_walk(node* z){if(z!=NULL){tree_walk(z->left);cout<<z->key<<' ';tree_walk(z->right);}}void bst_insert(tree* t,node* z){node* y=NULL;node* x=t->root;while(x!=NULL){y=x;if(z->key < x->key)x=x->left;else x=x->right;}z->p=y;if(y==NULL)t->root=z;else if(z->key < y->key)y->left=z;else y->right=z;}tree* persistent_tree_insert(tree* t,int k){node* y;// 追蹤新樹根node* x;// 指向舊樹的y->left or y->rightnode* x1;//指向新樹的y->left or y->righttree* T=new tree();if(t->root!=NULL)T->root=new node(t->root);//將舊樹root copy到新樹的root,前提是t->root不為空白,否則報錯cp->key不存在y=T->root; //y指向新樹根if(y==NULL)//如果樹為空白,只能將值插到新根{x1=new node(k);T->root=x1;x1->p=NULL;return T;}while(y!=NULL && y->key!=k){if(y->key < k){x=y->right;//指向舊樹y結點的下一結點if(x==NULL)x1=new node(k);//建立新樹結點elsex1=new node(x);//copy舊樹結點x到新樹結點x1y->right=x1;x1->p=y; y=x1;//這裡y指向x1和x都無所謂,因為x,x1的left,right指向都一樣,習慣指向新結點}else{x=y->left;//指向舊樹y結點的下一結點if(x==NULL)x1=new node(k);//建立新樹結點elsex1=new node(x);//copy舊樹結點x到新樹結點x1y->left=x1;x1->p=y; y=x1;//這裡y指向x1和x都無所謂,因為x,x1的left,right指向都一樣,習慣指向新結點}}return T;}void main(){int A[]={4,3,8,2,7,10};int len=sizeof(A)/sizeof(A[0]);node* z;tree* t=new tree();for(int i=0;i<len;i++){z=new node(A[i]);bst_insert(t,z);}tree_walk(t->root);cout<<endl;tree* T=persistent_tree_insert(t,5);cout<<"persistent_tree_insert"<<endl;tree_walk(T->root);}
c)時間與空間都是O(h)