自己實現的二叉搜索樹,可能不是什麼優秀的實現版本,但是好歹是自己通過學習二叉搜索樹的原理,然後摸索出的自己的實現版本。
這裏還用到了C++中的引用,雖然不是什麼大事,但一度困擾了我。
BST的原理可以在任何一本有關數據結構的教科書中找到,關鍵是如何用代碼實現。每個人的實現版本都不太一樣。
接下來,我要找一些簡潔高效而又正確的實現版本,提升自己的能力。
/*
二叉搜索樹模版
成員函數
一、查找函數
Node * Find(tree_node &root, int key)
功能:在根結點爲root的BST中查找關鍵值爲key的結點
二、插入函數
void Insert(tree_node &root, int key)
功能:在根結點爲root的BST中插入關鍵值爲key的結點
三、刪除函數
void DeleteNode(tree_node &root, tree_node u)
功能:在根結點爲root的BST中刪除結點u
*/
#include <cstdio>
#include <cstdlib>
struct Node {
int key;
Node *left, *right;
}*root = NULL;
typedef struct Node *tree_node;
//在根爲root的二叉搜索樹中找鍵值爲key的結點
Node * Find(tree_node &root, int key) {
tree_node u = root;
while (u != NULL && u->key != key) {
if (key < u->key)
u = u->left;
else
u = u->right;
}
return u;
}
//在根爲root的二叉搜索樹中插入鍵值爲key的結點
void Insert(tree_node &root, int key)
{
Node *z = (Node *)malloc(sizeof(Node));
Node *f = NULL, *x = root;
z->left = z->right = NULL;
z->key = key;
// 尋找結點f,其中f爲待插入結點z的父結點
while (x != NULL) {
f = x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
if (f != NULL) {
if (z->key < f->key)
f->left = z;
else
f->right = z;
} else
root = z; //根結點root爲空,插入結點就是根結點
return;
}
//刪除指定結點
void DeleteNode(tree_node &root, tree_node u)
{
bool L = false;//判斷結點u是否在它的父結點的左邊,是 L爲true,否則爲false
tree_node father = NULL, x = root;
//尋找結點u的父結點father
while (x != u) {
father = x;
if (u->key < x->key)
x = x->left;
else
x = x->right;
}
if (father != NULL && u->key < father->key) L = true;
//分類一: 結點u是葉子結點
if (u->left == NULL && u->right == NULL) {
free(u);
if (father != NULL) {
if (L) father->left = NULL;
else father->right = NULL;
} else
root = NULL; // father爲NULL,說明被剷除的是根結點root
}
//分類二(1): 結點u只有右子樹
else if (u->left == NULL && u->right != NULL) {
//如果u就是根結點root
if (u == root) {
root = u->right;
free(u);
} else {
//u不是根結點
if (L)
father->left = u->right;
else
father->right = u->right;
free(u);
}
}
//分類二(2): 結點u只有左子樹,原理同u只有左子樹相同
else if (u->left != NULL && u->right == NULL) {
if (u == root) {
root = u->left;
free(u);
} else {
if (L)
father->left = u->left;
else
father->right = u->left;
free(u);
}
} else {
//分類三: 結點u的左右子樹均存在
tree_node r = u->right, f = u;
//r存放結點u右子樹中最小的結點,f存放r的父結點
while (r->left != NULL) {
f = r;
r = r->left;
}
u->key = r->key;
if (f != u) //最小結點在結點u->right的左子樹中時
f->left = r->right;
else //最小結點就是u->right
f->right = r->right;
free(r);
}
return;
}
//前序遍歷的遞歸實現
void Preorder(Node *u)
{
if (u == NULL)
return;
printf(" %d", u->key);
Preorder(u->left);
Preorder(u->right);
}
//中序遍歷的遞歸實現
void Inorder(Node *u)
{
if (u == NULL)
return;
Inorder(u->left);
printf(" %d", u->key);
Inorder(u->right);
}
//後序遍歷的遞歸實現
void Postorder(Node *u)
{
if (u == NULL)
return;
Postorder(u->left);
Postorder(u->right);
printf(" %d", u->key);
}
int main()
{
int x;
char cmd[10];
while (scanf("%s", cmd) == 1) {
if (cmd[0] == 'f') {
scanf("%d", &x);
tree_node t = Find(root, x);
if (t != NULL) printf("yes\n");
else printf("no\n");
} else if (cmd[0] == 'i') {
scanf("%d", &x);
Insert(root, x);
} else if (cmd[0] == 'd') {
scanf("%d", &x);
tree_node u = Find(root, x);
DeleteNode(root, u);
} else if (cmd[0] == 'p') {
Inorder(root);
printf("\n");
Preorder(root);
printf("\n");
Postorder(root);
printf("\n");
} else
break;
}
return 0;
}