833系列——二叉排序樹
阿新 • • 發佈:2018-08-15
tree src 我們 不用 emp 刪除 假設 cout inf
考綱中,二叉排序樹在“查找”章節,要求為:二叉排序樹及其基本操作。
其基本操作有:查找操作,插入操作,刪除操作
一:定義
二叉排序樹(Binary Sort Tree),又稱二叉查找樹,它是一顆空樹,或者是具有以下性質的二叉樹:
若它的左子樹不空,則左子樹上所有結點的值均小於它的根節點的值。
若它的右子樹不空,則右子樹上所有結點的值均大於它的根節點的值。
它的左右子樹也都是二叉排序樹
二:首先定義一個二叉樹的結構
1 struct BSTree 2 { 3 int data; 4 BSTree *lchild, *rchild;5 BSTree(int d = 0, BSTree *l = NULL, BSTree *r = NULL) 6 { 7 data = d; 8 lchild = l; 9 rchild = r; 10 } 11 };
三:建立一個二叉排序樹
二叉排序樹的建立,其實就是由一個空樹,一個一個的插入數據形成的,也就是需要插入操作
而在插入操作中,我們需要找到插入數據合適的位置,這裏又可以看做是查找操作
插入操作有遞歸和循環兩種寫法
循環寫法:
void insertTree1(BSTree* &root, intkey) { if(root == NULL) { BSTree *s = new BSTree(key); root = s; return; } BSTree *t = root; while(t->data != key) { if(key > t->data && t->rchild != NULL) t = t->rchild; else if(key < t->data && t->lchild != NULL) t= t->lchild; else if(key > t->data && t->rchild == NULL) { BSTree *s = new BSTree(key); t->rchild = s; } else if(key < t->data && t->lchild == NULL) { BSTree *s = new BSTree(key); t->lchild = s; } } }
遞歸寫法:
void insertTree2(BSTree* &root, int key) { if(root == NULL) { BSTree *s = new BSTree(key); root = s; return; } if(key > root->data) insertTree2(root->rchild, key); else insertTree2(root->lchild,key); }
查找操作由插入操作簡單修改得到,不再上代碼
四:刪除操作(重點)
刪除節點有三種情況:
要刪除的點為葉子節點,直接刪除即可;
要刪除的點只有左子樹,或只有右子樹,刪除節點後,將左子樹或右子樹整體移動到被刪除節點的位置即可;
要刪除的節點即有左子樹,又有右子樹;
第一、二種情況可以合並為第二種,第三種情況比較復雜
根據二叉排序樹的定義,節點刪除後,這個位置應該由與它大小相鄰的數代替,對於下面這張圖:
假設要刪除的節點為47,那麽能夠代替這個位置的就是37和48,可以發現,這兩個數都有一個特點,37為47的左子樹中的最右子樹,48為47的右子樹的最左子樹
基於此可以這樣做:假定每次都用較小的數來代替,也就是37,此時51這邊整體就不用動了,只需要將37移動到47的位置,然後將37的整個左子樹移動到37原來的位置
代碼:
void Delete(BSTree* &node) { if(node->lchild == NULL) { BSTree *temp = node; node = node->rchild; delete(temp); } else if(node->rchild == NULL) { BSTree *temp = node; node = node->lchild; delete(temp); } else //用與該節點臨近且小於的點代替 { BSTree *newnode = node->lchild; BSTree *temp = node; while(newnode->rchild != NULL) { temp = newnode; newnode = newnode->rchild; } node->data = newnode->data; if(temp != node) temp->rchild = newnode->lchild; else temp->lchild = newnode->lchild; delete(newnode); } } void DeleteTree(BSTree* &root, int key) { if(root == NULL) return; if(key == root->data) Delete(root); else if(key > root->data) return DeleteTree(root->rchild, key); else return DeleteTree(root->lchild, key); }
五:遍歷及測試數據
建好二叉排序樹後,使用中序遍歷,即可得到一個排好序的數列
void InOrder(BSTree *root) { if(root != NULL) { InOrder(root->lchild); cout << root->data << " "; InOrder(root->rchild); } }
測試數據
int main() { int a[12] = {29, 36, 62, 88, 58, 47, 35, 73, 51, 99, 37, 93}; BSTree *root = NULL; for(int i=0; i<12; i++) { insertTree2(root, a[i]); } InOrder(root); cout << endl; DeleteTree(root, 47); InOrder(root); return 0; }
833系列——二叉排序樹