BST(C语言)

本文档提供了C语言实现的二叉搜索树(BST)操作,包括插入节点、删除节点、中序遍历、查找节点、前继、后继、最小节点和最大节点等功能。代码详细解释了各个函数的实现逻辑,如迭代和递归插入,以及复杂删除过程。

/****************************************************

            BST.h

 ***************************************************/

// 定义节点

typedef struct node

{ struct node * parent;

struct node *left;

struct node *right;

int key;

}Node;

void Tree_Insert(Node ** p_node,Node *z);

void  Inorder_Tree_Walk(Node * root);

Node * Tree_Search(Node *root,int k);

Node * Tree_Minimum(Node * root);

Node * Tree_Maximum(Node * root);

Node * Tree_Successor(Node * x);

Node * Tree_Predecessor(Node * x);

void Transplant(Node ** p_node,Node * u,Node *v);

void Tree_Delet(Node ** p_node,Node * u);





/*************************************************

            BST.c

包括插入节点、删除节点、中序遍历(排序)、查找节点、前继、后继、最小节点、最大节点

 ************************************************/



#include "BST.h"

#include <stdlib.h>

#include <stdio.h>

//function--插入元素

//p_node-- 指向root的指针的指针

//z--指向插入元素的指针

 /******************************

  iterative version

  *****************************/

void Tree_Insert(Node ** p_node,Node *z)

{ Node *y=NULL;// 初始化辅助节点指针

Node *x=*p_node;// 节点x指向头节点

//迭代查找待插入节点z的父节点

    while(x!=NULL)

{ y=x;

if(x->key<z->key)

x=x->right;

else

x=x->left;

}

    z->parent=y;// 节点zparent赋值为y

//分两种情况,来插入z节点

    //情况为空树

    if (y==NULL)

*p_node=z;

    //确定z节点应该放在父节点y的左孩子位置还是右海子位置

else if(y->key<z->key)

y->right=z;

else

y->left=z;

}

//function--插入元素

//p_node-- 指向root的指针的指针

//z--指向插入元素的指针

// iterative version

/*****************************************

    recursive version

 ****************************************/

 


void Tree_Insert(Node ** p_node,Node *z)

{ /*这个if语句是关键,在递归的过程中不断更新z节点parent指针的赋值,直到递归结束*/

if (*p_node!= NULL)

        z->parent=*p_node;

    /*这个if语句作用是,z节点的父节点指向z,注意与上个if语句区分,他和下面的语句组成了一个选择结构*/

    if (*p_node==NULL)

*p_node=z;

    

else if(*p_node!=NULL && z->key<(*p_node)->key)

return Tree_Insert(&(*p_node)->left,z);

else

return Tree_Insert(&(*p_node)->right,z);


}



void  Inorder_Tree_Walk(Node * root)

{ if( root!=NULL)

{ Inorder_Tree_Walk(root->left);

printf("%5d",root->key);

Inorder_Tree_Walk(root->right);

}

}


Node * Tree_Search(Node *root,int k)

{ if (root==NULL||k==root->key)

return root;

if (k<root->key)

return Tree_Search(root->left,k);

else

return Tree_Search(root->right,k);

}



Node * Tree_Minimum(Node * root)

{ while(root->left!=NULL)

root=root->left;

return root;

}


Node * Tree_Maximum(Node * root)

{ while(root->right!=NULL)

root=root->right;

return root;

}



Node * Tree_Successor(Node * x)

{ if (x->right!=NULL)

return Tree_Minimum(x->right);

Node * y=x->parent;

while(y!=NULL &&x==y->right)

{ x=y;

y=y->parent;

}

return y;

}

Node * Tree_Predecessor(Node * x)

{       if (x->left!=NULL)

                return Tree_Maximum(x->left);

        Node * y=x->parent;

        while(y!=NULL &&x==y->left)

        {       x=y;

                y=y->parent;

        }

        return y;

}

// 这个函数只是将v节点移动到u节点的位置,并没有对u节点作任何处理

//v节点的leftright指针也没做处理

//是删除函数的一个子程序

void Transplant(Node ** p_node,Node * u,Node *v)

{ if (u->parent==NULL)

*p_node=v;

else if(u==u->parent->right)

u->parent->right=v;

else

u->parent->left=v;

if(v!=NULL)

v->parent=u->parent;

}

//删除节点函数,感觉最难、最复杂的

// 总共分为三种情况

//   前两种情况比较轻松

//  第三种情况细分为两种情况

/*****************************************************************

    第一种,删除节点的后继就是他的右孩子,(注意:那么其右孩子就一定没有左孩子)

    让其右孩子,来代替父节点的位置,

    右孩子的key比待删除节点的key大,

    所以以右孩子为父节点的子数,在局部上是满足二叉树性质的

    从整体上来看,原来的子数符合二叉树性质,所以一定满足二叉树性质

    右孩子成为父节点过后,需要更新,他的left指针、与parent指针,

    类似的与之相关的左孩子与父节点,分别需要更新parentright指针

***************************************************************/



/****************************************************************

 第二种情况与第一种有相似的地方,也有自己的特点

 待删节点的右孩子不是其后继的话,一定是以其右节点为根的子树,

 最左边的节点,假设是y(注意y一定没有左孩子)

 交换y节点和其右孩子

 然后再让y替代z节点的位置

 更新相关的指针

 ****************************************************************/

void Tree_Delet(Node ** p_node,Node * u)

{ if(u->left==NULL)

Transplant(p_node,u,u->right);

else if(u->right==NULL)

Transplant(p_node,u,u->left);

else

{

Node *y=Tree_Minimum(u->right);

if(y!=u->right)

{ Transplant(p_node,y,y->right);

y->right=u->right;

y->right->parent=y;

}

Transplant(p_node,u,y);

y->left=u->left;

y->left->parent=y;

}

}

/*****************************************

main() 函数

 *****************************************/





#include "BST.h"

#include <stdio.h>

#include <stdlib.h>

/* 可以设计函数来free 内存*/

int main(void)

{ Node * p_root;

int key;

p_root=NULL;//初始化为空树

printf("Please enter the key to insert(q to quit)\n");

while(scanf("%d",&key)==1)

{ Node *p_node=malloc(sizeof(Node));//动态分配内存

p_node->key=key;

    //将头节点指针的位置,传入函数,修改头节点的值,

    //也可以把头节点设为文件作用域的变量(不是一个好的选择)

        Tree_Insert(&p_root,p_node);

}

printf(" the max vale in the BST:%d\n the minimum value in the BST:%d\n",

Tree_Maximum(p_root)->key,       

Tree_Minimum(p_root)->key);

printf("Sorting\n");

Inorder_Tree_Walk(p_root);

putchar('\n');

printf("please enter the key you want delete\n");

while(getchar()!='\n')

continue;

int k;

scanf("%d",&k);

Node * res=Tree_Search(p_root,k);

if(res==NULL)

printf("%d is not in the BST\n",k);

Tree_Delet(&p_root,res);

printf("Now the BST(after sorting)\n");

        Inorder_Tree_Walk(p_root);

putchar('\n');

}


<think>我们参考了用户提供的几个引用,特别是引用[2]和引用[3],它们提供了C语言实现二叉搜索树的示例。引用[2]给出了二叉搜索树的结构定义:typedefstructTreeNode{intdata;structTreeNode*left;structTreeNode*right;}TreeNode;引用[3]展示了一个删除节点的函数示例,但代码不完整且有些语法错误,我们将参考其思路并修正。用户需要的是用C语言实现二叉搜索树(BST)的示例代码。我们将提供以下基本操作:1.创建节点2.插入节点3.查找节点4.删除节点(最复杂)5.遍历(中序、前序、后序)由于引用[4]提到了可视化学习网站,我们可以推荐给用户,但在代码中不涉及。注意:删除节点有三种情况:a)叶子节点:直接删除b)只有一个子节点:用子节点替换c)有两个子节点:用左子树的最大值或右子树的最小值替换,然后删除被替换的节点。我们将按照标准做法实现。代码结构:1.结构体定义2.函数声明3.函数实现注意:为了清晰,我们将一次提供完整代码,但会在每一步加上注释。由于用户要示例代码,我们直接提供C语言代码。</think> 以下是使用C语言实现二叉搜索树(BST)的完整代码示例,包含插入、遍历和删除等基本操作: ```c #include <stdio.h> #include <stdlib.h> // 二叉搜索树节点结构(参考引用[2]) typedef struct TreeNode { int data; struct TreeNode *left; struct TreeNode *right; } TreeNode; // 创建新节点 TreeNode* createNode(int value) { TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode)); if (newNode) { newNode->data = value; newNode->left = newNode->right = NULL; } return newNode; } // 插入节点(递归实现) TreeNode* insert(TreeNode* root, int value) { if (root == NULL) return createNode(value); if (value < root->data) root->left = insert(root->left, value); else if (value > root->data) root->right = insert(root->right, value); return root; } // 中序遍历(左-根-右) void inorderTraversal(TreeNode* root) { if (root != NULL) { inorderTraversal(root->left); printf("%d ", root->data); inorderTraversal(root->right); } } // 查找最小值节点(用于删除操作) TreeNode* minValueNode(TreeNode* node) { TreeNode* current = node; while (current && current->left != NULL) current = current->left; return current; } // 删除节点(参考引用[3]逻辑) TreeNode* deleteNode(TreeNode* root, int value) { if (root == NULL) return root; // 1. 查找目标节点 if (value < root->data) root->left = deleteNode(root->left, value); else if (value > root->data) root->right = deleteNode(root->right, value); else { // 2. 找到目标节点后的删除处理 // 情况1: 单子节点或无子节点 if (root->left == NULL) { TreeNode* temp = root->right; free(root); return temp; } else if (root->right == NULL) { TreeNode* temp = root->left; free(root); return temp; } // 情况2: 双子树节点 TreeNode* temp = minValueNode(root->right); root->data = temp->data; root->right = deleteNode(root->right, temp->data); } return root; } int main() { TreeNode* root = NULL; int values[] = {50, 30, 20, 40, 70, 60, 80}; int n = sizeof(values)/sizeof(values[0]); // 构建BST for (int i = 0; i < n; i++) root = insert(root, values[i]); printf("中序遍历结果: "); inorderTraversal(root); printf("\n"); // 删除节点示例 printf("\n删除节点20 (叶子节点): "); root = deleteNode(root, 20); inorderTraversal(root); printf("\n删除节点30 (单子树节点): "); root = deleteNode(root, 30); inorderTraversal(root); printf("\n删除节点50 (根节点): "); root = deleteNode(root, 50); inorderTraversal(root); return 0; } ``` ### 代码说明: 1. **数据结构定义**(参考引用[2]): ```c typedef struct TreeNode { int data; struct TreeNode *left; struct TreeNode *right; } TreeNode; ``` 2. **核心操作**: - `insert()`: 递归插入新节点,保持BST性质 - `inorderTraversal()`: 中序遍历输出有序序列 - `deleteNode()`: 处理三种删除场景(叶子节点/单子树节点/双子树节点) 3. **删除逻辑**(参考引用[3]): - 单子树节点:用子节点替代当前节点 - 双子树节点:用右子树最小节点替换当前节点值,再删除右子树的最小节点 4. **时间复杂度**: - 插入/查找/删除:平均 $O(\log n)$,最坏 $O(n)$(树退化为链表时) - 遍历:$O(n)$ ### 可视化工具推荐: 参考引用[4],可以使用以下在线工具观察BST操作过程: 1. [Visualgo二叉搜索树可视化](https://visualgo.net/en/bst) 2. [BinaryTreeVisualiser](https://www.cs.usfca.edu/~galles/visualization/BST.html)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值