程式設計師面試寶典_第13章_資料結構基礎_排序演算法小結(4)
阿新 • • 發佈:2019-02-05
十、二叉樹排序演算法
[演算法思想]:二叉排序樹(Binary Sort Tree)又稱二叉查詢樹,亦稱二叉搜尋樹。 它或者是一棵空樹;或者是具有下列性質的二叉樹:
(1)若左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
(2)若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;
(3)左、右子樹也分別為二叉排序樹;
刪除演算法
相對查詢和插入複雜一點,根據待刪除結點的孩子情況,分三種情況:沒有孩子,只有一個孩子,有兩個孩子。
沒有孩子的情況,其父結點指向空,刪除該結點。
有一個孩子的情況,其父結點指向其孩子,刪除該結點。
有兩個孩子的情況,當前結點與左子樹中最大的元素交換,然後刪除當前結點。左子樹最大的元素一定是葉子結點,交換後,當前結點即為葉子結點,刪除參考沒有孩子的情況。另一種方法是,當前結點與右子樹中最小的元素交換,然後刪除當前結點。
說明如下:
1、刪除的是“葉節點20“,,刪除20不會破壞樹的結構。如圖:
2、刪除”單孩子節點90“,需要把他的孩子頂上去
3、刪除“左右孩子都有的節點50”,就是找到右節點的左子樹最左孩子。
比如:首先 找到50的右孩子70。
然後 找到70的最左孩子,發現沒有,則返回自己。
最後 原始圖和最終圖如下。
終於改對了,對於我這智商程式設計太辛苦了~
#include <iostream> using namespace std; class BinaryTree; class node; void Show(node * t); class node { public: friend class BinaryTree; friend void Show(node * t); node(){key=0;leftchild=NULL;rightchild=NULL;} node(int x){key=x;leftchild=NULL;rightchild=NULL;} private: int key; node* leftchild; node* rightchild; }; void Show(node * t) { cout<<t->key<<" "; } class BinaryTree { public: BinaryTree(){head=NULL;} ~BinaryTree(){}; void Search(int data) { node * p=SearchP(head,data); if (p) { cout<<"Find: "<<"Address: 0x"<<hex<<p<<" , "<<"Value: "<<dec<<p->key<<endl; }else { cout<<"Can't Find the key! "<<endl; } } void Insert(int data){InsertP(&head,data);} void SearchInsert(int data) { node * p=SearchP(head,data); if (p) { cout<<"Find: "<<"Address: 0x"<<hex<<p<<" , "<<"Value: "<<dec<<p->key<<endl; }else { cout<<"Can't Find the key! Insert the key "<<data<<" in the tree!"<<endl; Insert(data); InOrder(); cout<<endl; } } void Create(int A[],int length); void Delete(int data); void InOrder() { InOrderP(Show,head); } private: node * head; node * SearchP(node * t,int data) { if (t==NULL) { return NULL; } if (t->key==data) { return t; } if (data<t->key) { SearchP(t->leftchild,data); } else { SearchP(t->rightchild,data); } } void InOrderP(void (*Show)(node* n),node* t) { if (t==NULL) { return; } InOrderP(Show,t->leftchild); Show(t); InOrderP(Show,t->rightchild); } node * InsertP(node** t,int data)//由於可能會改變頭指標,因此改用二重指標 { if ((*t)==NULL)//不存在,所以插入 { (*t)=new node(data); return (*t); } if (data<(*t)->key) { (*t)->leftchild=InsertP(&((*t)->leftchild),data); } else if (data>(*t)->key) { (*t)->rightchild=InsertP(&((*t)->rightchild),data); } return (*t); } }; void BinaryTree::Create(int A[],int length) { for (int i=0;i<length;i++) { Insert(A[i]); } } void BinaryTree:: Delete(int data) { node *p=head; node *pp=p; //p's parent node *temp; while (p!=NULL) { if (p->key==data) { break; } else if (data<p->key) { pp=p; p=p->leftchild; } else { pp=p; p=p->rightchild; } } if(!p)//沒找到 { cout<<"Data "<<data<<" doesn't exist!!! Delete Fail!!!!"<<endl; } else //找到了 { if(p->leftchild==NULL&&p->rightchild==NULL)//該節點為葉子節點的情況,case1 { if(p==head)//為根節點 { delete head; head=NULL; } else//不是根節點 { if(pp->leftchild==p)//如果p為pp的左孩子 { pp->leftchild=NULL; delete p; p=NULL; } else//p為pp的右孩子 { pp->rightchild=NULL; delete p; p=NULL; } } } else if(p->leftchild==NULL&&p->rightchild!=NULL)//該節點只有1個右孩子情況,case2 { if(p==head)//為根節點 { temp=p->rightchild; delete head; head=temp; } else//不是根節點 { if (pp->leftchild==p)//如果p為pp的左孩子 { pp->leftchild=p->rightchild; delete p; p=NULL; } else//p為pp的右孩子 { pp->rightchild=p->rightchild; delete p; p=NULL; } } } else if(p->leftchild!=NULL&&p->rightchild==NULL)//該節點只有1個左孩子情況,case3 { if(p==head)//為根節點 { temp=p->leftchild; delete head; head=temp; } else//不是根節點 { if(pp->leftchild==p)//如果p為pp的左孩子 { pp->leftchild=p->leftchild; delete p; p=NULL; } else//p為pp的右孩子 { pp->rightchild=p->leftchild; delete p; p=NULL; } } } else//有兩個孩子的情況 { node *q=p->rightchild;//找到右節點左子樹的最左孩子; node *qp=p;//q的父節點 while (q->leftchild!=NULL) { qp=q; q=q->leftchild; } p->key=q->key; if (q->rightchild!=NULL)// { if (qp!=p) { qp->leftchild=q->rightchild; delete q; q=NULL; } else { qp->rightchild=q->rightchild; delete q; q=NULL; } } else// { if (qp!=p) { qp->leftchild=NULL; delete q; q=NULL; } else { qp->rightchild=NULL; delete q; q=NULL; } } } } } int main() { int A[10]={13, 29, 27, 28, 26, 30, 38, 54 , 68 ,36}; BinaryTree BT; BT.Create(A,10); BT.InOrder(); int data; cout<<endl; while(1) { cout<<endl; cout<<"請輸入要查詢的資料: "<<endl; cin>>data; BT.SearchInsert(data); cout<<"請輸入要刪除的資料: "<<endl; cin>>data; BT.Delete(data); BT.InOrder(); } system("pause"); return 0; }