/*
二叉排序樹,這裏例子的結點只給出關鍵字 key
插入過程相當於動態排序,可以有折半搜索和線性搜索的性質
最差情況是導致線性搜索,例如下面的例子都是右子樹
改進可以用平衡二叉樹或稱AVL樹或稱紅黑樹,從而壓縮樹深度,越接近折半搜索
*/
#include<iostream>
#include<queue>
using namespace std;
struct node {
int key;
node *lchild;
node *rchild;
};
node *root;
node *father;
//若找到返回結點的指針,沒找到返回NULL。傳入參數,記錄當前查找結點的父結點指針
node *find(int key) {
//這裏查找root若空,父指針這裏也空.當在父節點找到了,父指針也爲空
father=NULL;
if(!root) {
return NULL;
}
node *temp=root;
while(temp) {
if(key==temp->key) {
return temp;
} else if(key<root->key) {
father=temp;
temp=temp->lchild;
} else {
father=temp;
temp=temp->rchild;
}
}
return NULL;
}
bool insert(int key) {
if(!root) {
root=new node();
root->key=key;
printf("空樹,已插入爲根結點!key=%d\n",key);
return true;
}
//root!=NULL的情況
father=NULL;
node *p=find(key);
if(p) {
return true;
}
//在這裏father不可能是空的
if(father) {
node *temp=new node();
temp->key=key;
if(key<father->key) {
father->lchild=temp;
} else {
father->rchild=temp;
}
printf("已插入!\n");
return true;
}
}
//獲取結點下子樹的最小key結點,即最左邊的結點
node *getmin(node *root) {
if(!root)return NULL;
if(!root->lchild) {
return root;
}
return getmin(root->lchild);
}
//二叉排序樹刪除:!只刪除一個結點,刪除後其他結點仍保持二叉排序樹的性質(有兩種方法)
//有三種情況,刪樹的根結點,刪葉結點,刪有子樹的結點(父結點不是樹的根結點)
bool del(int key) {
if(!root)return false;
node *temp=find(key);
if(!temp)return false;
//別漏了刪除根節點的情況
if(temp==root) {
node *l=getmin(root->rchild);
l->lchild=root->lchild;
root=root->rchild;
return true;
}
//別漏了葉節點情況
if(!temp->lchild&&!temp->rchild) {
if(father->lchild==temp) {
father->lchild=NULL;
} else {
father->rchild=NULL;
}
delete temp;
return true;
}
if(father->lchild==temp) {
if(temp->rchild) {
father->lchild=temp->rchild;
if(temp->lchild) {
//這裏的temp->rchild已判斷不爲空,返回的肯定不爲空
node *p=getmin(temp->rchild);
p->lchild=temp->lchild;
return true;
}
} else if(temp->lchild) {
father->lchild=temp->lchild;
return true;
}
} else if(father->rchild==temp) {
if(temp->rchild) {
father->rchild=temp->rchild;
if(temp->lchild) {
//這裏的temp->rchild已判斷不爲空,返回的肯定不爲空
node *p=getmin(temp->rchild);
p->lchild=temp->lchild;
return true;
}
} else if(temp->lchild) {
father->rchild=temp->lchild;
return true;
}
}
return false;
}
void out(node *root) {
if(root) {
out(root->lchild);
out(root->rchild);
printf("%d ",root->key);
}
}
int main() {
insert(1);
insert(2);
insert(3);
insert(4);
insert(5);
insert(6);
out(root);
printf("\n");
del(1);
del(4);
del(6);
del(3);
printf("del...\n");
out(root);
printf("\n");
return 0;
}
二叉排序樹
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.