github地址:https://github.com/jobbofhe/Learning_Data_Structure_and_Algorithms
/*
* @Author: jobbofhe
* @Date: 2019-07-29 20:08:30
* @Last Modified by: Administrator
* @Last Modified time: 2019-08-07 20:11:18
*/
#include <stdio.h>
#include <stdlib.h>
typedef int TYPE;
// 二叉查找樹的節點包含的基本信息:
// (01) key -- 它是關鍵字,是用來對二叉查找樹的節點進行排序的。
// (02) left -- 它指向當前節點的左孩子。
// (03) right -- 它指向當前節點的右孩子。
// (04) parent -- 它指向當前節點的父結點。
typedef struct BSTreeNode
{
TYPE key;
struct BSTreeNode *left;
struct BSTreeNode *right;
struct BSTreeNode *parent;
}Node, *BSTree;
Node *create_bstree_node(TYPE key, Node *parent, Node *left, Node *right);
Node *insert_bstree(BSTree tree, TYPE key);
// 前根序遍歷
void pre_order_bstree(BSTree tree);
// 中根序遍歷
void middle_order_bstree(BSTree tree);
// 後根序遍歷
void behind_order_bstree(BSTree tree);
// 中根序
// 遞歸方式
// 在二叉樹中,查找值爲key的節點
Node *bstree_search_recursion(BSTree tree, TYPE key);
// 中根序
// 循環方式
// 在二叉樹中,查找值爲key的節點
Node *bstree_search(BSTree tree, TYPE key);
// 中根序,查找最大值
Node *bstree_search_max(Node *pnode);
// 中根序,朝趙最小值
Node *bstree_search_min(Node *pnode);
// 中根序,查找 某結點的前驅
Node *bstree_search_predecessor(Node *pnode);
// 中根序,查找 某結點的後繼結點
Node *bstree_search_successor(Node *pnode);
// 內部接口
// 中根序 向樹tree中插入一個結點,返回插入後的樹的根節點
static Node *bstree_insert(BSTree tree, Node *newNode);
// 外部接口,在樹中新建結點,並返回根節點
Node *create_bstree(BSTree tree, TYPE key);
// 刪除節點
static Node *bstree_delete_node(BSTree tree, Node *dstNode);
// 打印整顆二叉樹(tree)。其中,tree是二叉樹節點,key是二叉樹的鍵值,而direction表示該節點的類型:
// direction爲 0,表示該節點是根節點;
// direction爲-1,表示該節點是它的父結點的左孩子;
// direction爲 1,表示該節點是它的父結點的右孩子。
void printf_bstree(BSTree tree, TYPE key, int direction);
void destroy_bstree(BSTree tree);
Node *create_bstree_node(TYPE key, Node *parent, Node *left, Node *right)
{
Node *p = (Node*)malloc(sizeof(Node));
if (NULL == p)
{
printf("Faild to malloc!\n");
return NULL;
}
p->key = key;
p->parent = parent;
p->left = left;
p->right = right;
return p;
}
Node *insert_bstree(BSTree tree, TYPE key)
{
Node * pnode = create_bstree_node(key, NULL, NULL, NULL);
if (NULL == pnode)
{
printf("Faile create bstree node!\n");
return tree;
}
return tree;
}
// 前根序遍歷
void pre_order_bstree(BSTree tree)
{
if (NULL == tree)
{
return ;
}
printf("%d ", tree->key);
pre_order_bstree(tree->left);
pre_order_bstree(tree->right);
}
// 中根序遍歷
void middle_order_bstree(BSTree tree)
{
if (NULL == tree)
{
return ;
}
middle_order_bstree(tree->left);
printf("%d ", tree->key);
middle_order_bstree(tree->right);
}
// 後根序遍歷
void behind_order_bstree(BSTree tree)
{
if (NULL == tree)
{
return ;
}
behind_order_bstree(tree->left);
behind_order_bstree(tree->right);
printf("%d ", tree->key);
}
// 中根序
// 遞歸方式
// 在二叉樹中,查找值爲key的節點
Node *bstree_search_recursion(BSTree 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);
}
}
// 中根序
// 循環方式
// 在二叉樹中,查找值爲key的節點
Node *bstree_search(BSTree tree, TYPE key)
{
if (NULL == tree)
{
return tree;
}
while(NULL != tree && (tree->key != key))
{
if (key < tree->key)
{
tree = tree->left;
}
else
{
tree = tree->right;
}
}
return tree;
}
// 中根序,查找最大值
Node *bstree_search_max(Node *pnode)
{
if (NULL == pnode)
{
return pnode;
}
while(pnode->right != NULL)
{
pnode = pnode->right;
}
return pnode;
}
// 中根序,朝趙最小值
Node *bstree_search_min(Node *pnode)
{
if (NULL == pnode)
{
return pnode;
}
while(pnode->left != NULL)
{
pnode = pnode->left;
}
return pnode;
}
// 中根序,查找 某結點的前驅
Node *bstree_search_predecessor(Node *pnode)
{
if (NULL == pnode)
{
return pnode;
}
// 如果 pnode 存在左孩子,則它的前驅是,以它的左孩子爲根節點的子樹的最大結點
while(NULL != pnode->left)
{
return bstree_search_max(pnode->left);
}
// 如果 pnode 沒有左孩子,則有以下兩種可能
// 1) pnode 是一個右孩子,那麼他的前驅就是 它的父節點
// 2) pnode 是一個左孩子,那麼 查找 pnode 的最低的 父節點,並且該父節點要具有右孩子, 找到的這個最低的父節點 就是 x的前驅節點
Node *tmp = pnode->parent;
while(NULL != tmp && (pnode == tmp->left))
{
pnode = tmp;
tmp = tmp->parent;
}
return tmp;
}
// 中根序,查找 某結點的後繼結點
Node *bstree_search_successor(Node *pnode)
{
if (NULL == pnode)
{
return pnode;
}
// 如果 pnode 存在右孩子,則它的後繼就是他的右孩子
while(NULL != pnode->left)
{
return bstree_search_max(pnode->left);
}
// 如果 pnode 沒有右孩子,則有以下兩種可能
// 1) pnode 是一個左孩子,那麼他後繼就是 它的父節點
// 2) pnode 是一個右孩子,那麼 查找 pnode 的最低的 父節點,並且該父節點要具有左孩子, 找到的這個最低的父節點 就是 x的後繼節點
Node *tmp = pnode->parent;
while(NULL != tmp && (pnode == tmp->left))
{
pnode = tmp;
tmp = tmp->parent;
}
return tmp;
}
// 內部接口
// 中根序 向樹tree中插入一個結點,返回插入後的樹的根節點
static Node *bstree_insert(BSTree tree, Node *newNode)
{
if (newNode == NULL)
{
return tree;
}
Node *pTree = tree;
Node *pTmp = NULL;
// 找到要插入的位置
while(NULL != pTree)
{
pTmp = pTree;
// 新節點小於根節點
if (newNode->key < pTree->key)
{
pTree = pTree->left;
}
else if(newNode->key > pTree->key) // 新節點大於根節點
{
pTree = pTree->right;
}
else // 新節點等於根節點
{
free(newNode);
return tree;
}
}
newNode->parent = pTmp;
// 如果沒有找到要插入的位置,即tree爲空
if(pTmp == NULL)
{
tree = newNode;
}
else if (newNode->key < pTmp->key)
{
pTmp->left = newNode;
}
else
{
pTmp->right = newNode;
}
return tree;
}
// 外部接口,在樹中新建結點,並返回根節點
Node *create_bstree(BSTree tree, TYPE key)
{
Node *newNode;
// 創建新結點
newNode = create_bstree_node(key, NULL, NULL, NULL);
if (NULL == newNode)
{
return tree;
}
return bstree_insert(tree, newNode);
}
// 刪除節點
static Node *bstree_delete_node(BSTree tree, Node *dstNode)
{
Node *x = NULL;
Node *y = NULL;
// 根據要刪除的結點的類型,確定要刪除的節點或者他的後繼
if (dstNode->left == NULL || dstNode->right == NULL)
{
y = dstNode;
}
else // 左右孩子都不爲空
{
// 查找要刪除的節點的 後繼
y = bstree_search_successor(dstNode);
}
if (y->left != NULL)
{
x = y->left;
}
else
{
x = y->right;
}
if (x != NULL)
{
x->parent = y->parent;
}
if (y->parent == NULL)
{
tree = x;
}
else if (y == y->parent->left)
{
y->parent->left = x;
}
else
{
y->parent->right = x;
}
if (y != dstNode)
{
dstNode->key = y->key;
}
if (y != NULL)
{
free(y);
}
return tree;
}
// 刪除值爲key的節點
Node* bstree_delete_key(BSTree tree, TYPE key)
{
Node *z, *node;
if ((z = bstree_search(tree, key)) != NULL)
tree = bstree_delete_node(tree, z);
return tree;
}
// 打印整顆二叉樹(tree)。其中,tree是二叉樹節點,key是二叉樹的鍵值,而direction表示該節點的類型:
// direction爲 0,表示該節點是根節點;
// direction爲-1,表示該節點是它的父結點的左孩子;
// direction爲 1,表示該節點是它的父結點的右孩子。
void printf_bstree(BSTree tree, TYPE key, int direction)
{
if (NULL == tree)
{
return;
}
// 根節點
if (0 == direction)
{
printf("%3d is root.\n", tree->key);
}
else
{
printf("%3d is %3d's %6s child.\n", tree->key, key, direction == 1?"right":"left");
}
printf_bstree(tree->left, tree->key, -1);
printf_bstree(tree->right, tree->key, 1);
}
void destroy_bstree(BSTree tree)
{
if (tree == NULL)
{
return;
}
if (tree->left != NULL)
{
destroy_bstree(tree->left);
}
if (tree->right != NULL)
{
destroy_bstree(tree->right);
}
free(tree);
}
static int arr[] = {3, 54, 6, 7, 43, 9, 59, 55, 0, 2};
int main(int argc, char const *argv[])
{
Node *root;
int i = 0;
printf("--> 新建結點: ");
for (i=0; i < 10; ++i)
{
printf("%d ", arr[i]);
root = create_bstree(root, arr[i]);
}
printf("\n--> 前序遍歷: ");
pre_order_bstree(root);
printf("\n--> 中序遍歷: ");
middle_order_bstree(root);
printf("\n--> 後序遍歷: ");
behind_order_bstree(root);
printf("\n--> 最大值: ");
Node *max = bstree_search_max(root);
printf(" %d", max->key);
printf("\n--> 最小值: ");
Node *min = bstree_search_min(root);
printf(" %d", min->key);
printf("\n--> 查找55節點: ");
Node *node = bstree_search(root, 55);
printf(" %d", node->key);
printf("\n--> 打印二叉樹:\n");
printf_bstree(root, root->key, 0);
bstree_delete_key(root, 55);
printf("\n--> 最大值: ");
max = bstree_search_max(root);
printf(" %d", max->key);
printf("\n--> 前序遍歷: ");
pre_order_bstree(root);
printf("\n");
destroy_bstree(root);
return 0;
}