二叉搜尋樹的原始碼分析學習 筆記(基礎版)
阿新 • • 發佈:2018-12-12
二叉搜尋樹結構
typedef struct bst_tree_node
{
type key;
struct bst_tree_node * left;
struct bst_tree_node * right;
struct bst_tree_node * parent;
} node, * bst_tree;
有了二叉搜尋樹的儲存結構,那麼就應該知道怎麼建立
先建立一個結點
static node * create_bstree_node (type key, node * parent, node * left, node * right)
{
node * p;
if((p = (node * ) malloc(sizeof(node))) == NULL)
return NULL;
p->key = key;
p->left = left;
p->right = right;
p->parent = parent;
return p;
}
建立好結點後,再插入到樹中。插入的基本要求要保持二叉搜尋樹的屬性不能被破壞
/**
* 演算法理解方式是找準位置,然後插入。哈哈,很有意思。切記:找準位置最重要
*/
// tree是根結點 z是插入結點
static node * bstree_insert(bst_tree tree, node * z)
{
node * y = NULL;
node * x = tree;
//迴圈找到適合插入的葉子結點位置
while(x != NULL)
{
y = x;
if(z->key < x->key)
x = x->left;
else if(z->key > x->key)
x = x->right;
else
{
free(z); //如果相同key值結點,釋放此結點不執行插入
return tree;
}
}
//找到合適的位置後,再插入結點
z->parent = y;
if(y == NULL)
tree=z;
else if(z->key < y->key)
y->left = z;
else
y->right = z;
return tree;
}
二叉搜尋樹建立好了後,要開始遍歷,下面是三種遍歷方式。函式的形參是二叉搜尋樹的根節點指標。
//先序遍歷方式
void preorder_bsttree(bst_tree tree)
{
if(tree != NULL)
{
printf("%d ", tree->key);
preorder_bsttree(tree->left);
preorder_bsttree(tree->right);
}
}
//中序遍歷方式
void inorder_bstree(bst_tree tree)
{
if(tree != NULL)
{
inorder_bstree(tree->left);
printf("%d ", tree->key);
inorder_bstree(tree->right);
}
}
//後序遍歷方式
void postorder_bstree(bst_tree tree)
{
if(tree != NULL)
{
postorder_bstree(tree->left);
postorder_bstree(tree->right);
printf("%d ", tree->key);
}
}
根據一個值key查詢到對應的結點方法
/**
* 根據值 key,查詢對應的結點並返回對應的地址
* 第一步要判斷這個值 key是否合法,當然了這個是很簡單的
* 下面一步就體現出二叉搜尋樹的特點了
* 第一步到根節點,key如果大於根節點那麼到右結點下面去比較
* key如果小於根節點那麼到左結點下面去比較
* 就是這樣執行下去知道結點為空為止
*/
node * bstree_search(bst_tree tree, type key)
{
if(tree == NULL || tree->key == key)
return tree;
if(key < tree->key)
return bstree_search(tree->left, key);
else
return bstree_search(tree->right, key);
}
取得二叉搜尋樹中某個結點的後繼結點存在兩種情況
- x右子樹不為空,那麼它的後繼結點就是右子樹中最小的一個
- 如果x結點在根節點的左子樹中 且x結點是一個右子結點不含右子結點(下圖的13結點) 。那麼它的後繼結點就是x的最低父親結點(最低父親結點的條件是:父親結點的左結點等於x)
//查詢某個結點的後繼結點 比如 1 2 3 4 5,查詢3的後繼結點就是4
node * bstree_successor(node * x)
{
//如果x存在右子樹,則"x的後繼結點"為 "以其右孩子為根的子樹的最小結點"
if(x->right != NULL)
return bstree_minimum(x->right);
//如果x沒有右子樹
//x是一個左孩子,則x的後繼節點為他的父親結點
//x是一個右孩子,則x的最低父親結點,並且該父親結點的左結點等於x
node * y = x->parent;
while((y!=NULL) && (x == y->right))
{
x=y;
y = y->parent;
}
return y;
}
/**
* 二叉搜尋樹是一個很有意思的東西,
* 如果要尋找是最大的結點,那麼就在右子樹裡尋找,如果右子樹為空,那麼就是當前的根節點
* 同理:如果要尋找是最小的結點,那麼就在左子樹裡尋找,如果左子樹為空,那麼就是當前的根節點
*/
//左子樹最左一個結點值是最小的一個結點
node * bstree_minimum(bst_tree tree)
{
if(tree == NULL)
return NULL;
while(tree->left != NULL)
tree = tree->left;
return tree;
}
//右子樹最右的一個結點值是最大的一個結點
node * bstree_maximum(bst_tree tree)
{
if(tree == NULL)
return NULL;
while(tree->right != NULL)
tree= tree->right;
return tree;
}