BST(C语言)

来源:互联网 发布:javascript复选框全选 编辑:程序博客网 时间:2024/06/11 13:22

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

            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的左孩子位置还是右海子位置

elseif(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;

    

elseif(*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;

elseif(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);

elseif(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');

}


0 0