zoukankan      html  css  js  c++  java
  • BST(二叉排序树)的插入与删除

    值得一说的是删除操作,删除操作我们分为三种情况:

    1.要删的节点有两个孩子:

      找到左子树中的最大值或者右子树中的最小值所对应的节点,记为node,并把node的值赋给要删除的节点del,然后删除node

    实际上真正删除的是node,del只是发生了一次值的替换。

    为了方便理解和操作,我们把两个孩子的情况放在最前面,这样经过以上处理后,该节点就会变成情况2或者情况3 ,接下爱这行这两种情况的代码。

    2.要删的节点有一个孩子

    r判断要删除的节点del是其父亲father的左孩子还是右孩子,以是father的左孩子为例,del是father的左孩子,接下来判断del是否有左孩子,

    如果有,则father的左孩子变成del的左孩子,如果没有,则father的左孩子变成del的右孩子。

    3.要删的节点没有孩子

    即为当情况2 del的左孩子右孩子为空的时候

    #include<stdio.h>
    #include<stdlib.h>
    typedef struct Tree
    {
    	int data;
    	Tree*right;
    	Tree*left;
    }BinaryTree;
    void insert(BinaryTree **p,int e)
    {
    	BinaryTree *temp=(BinaryTree*)malloc(sizeof(BinaryTree));
    	temp->data=e;
    	temp->left=NULL;
    	temp->right=NULL;
    
    	if(*p==NULL)
    	{
    		*p=temp;
    		return ;
    	}
    	BinaryTree*root=*p;
    	while(1)
    	{
    		if(e<root->data)
    		{
    			if(root->left)
    			{
    				root=root->left;
    			}
    			else
    			{
    				root->left=temp;
    				break;//完成插入操作了
    			}
    
    		}
    		else if(e>root->data)
    		{
    			if(root->right)
    			{
    				root=root->right;
    
    			}
    			else
    			{
    				root->right=temp;
    				break;
    			}
    		}
    	}
    }
    void  FindNode(BinaryTree* p,BinaryTree **del,BinaryTree**father, int e)//我们在删除操作中不仅需要知道要删除哪个节点,还要知道要删除节点的父亲
    {                                          //return无法返回两个值,要实现返回两个值,我们在这里采用二级指针
    	while(1)                                                                    //实际上也可以通过结构体封装来完成同时返回两个值
    	{
    		if(e<p->data)
    		{  
    			*father=p;//每次都记录一下父亲
    			p=p->left;
    		}
    		else if(e>p->data)
    		{
    			*father=p;
    			p=p->right;
    		}
    		else if(e==p->data)
    		{
    			*del=p;return ;	
    		}
    	}
    }
    void deleteNode(BinaryTree **p,int e)//
    {
    	if(*p==NULL) return ;
    	BinaryTree *root=*p;
    	BinaryTree *del=NULL;
    	BinaryTree *father=NULL;
    	BinaryTree *pmark=NULL;
    	FindNode(root,&del,&father,e);
    	if(del->left&&del->right)
    	{
    		pmark=del;//标记要删除的点
    		father=del;
    		del=del->left;
    		while(del->right)
    		{
    			father=del;
    			del=del->right;
    		}
    		pmark->data=del->data;
    	}
    	//接下来分析有一个或者没有孩子的情况
    	//被删节点 是根
    	if(father==NULL)//??
    	{
    		*p=del->left?del->left:del->right;
    		free(del);
    		return ;
    	}
    	else
    	{//不用在写判断条件了,走到这说明就是一个或者没有孩子,只需要判断是哪边的孩子就可
    		if(del==father->left)
    			father->left=del->left?del->left:del->right;
    		else if(del==father->right)
    			father->right=del->left?del->left:del->right;
    		free(del);
    
    	}
    }
    void inorder(BinaryTree *p)
    {
    	if(p==NULL) return ;
    	//递归要有结束条件
    	inorder(p->left);
    	printf(" %d ",p->data);
    	inorder(p->right);
    }
    void preorder(BinaryTree *p)
    {
    	if(p==NULL) return ;
    	//递归要有结束条件
    	
    	printf(" %d ",p->data);
    	preorder(p->left);
    	preorder(p->right);
    }
    int main()
    {
    	int m;
    	BinaryTree *p=NULL;
    	int a[10];
    	int i;
    	scanf("%d",&m);
    	for(i=0;i<m;i++)
    	{
    		scanf("%d",&a[i]);
    	}
    	for(i=0;i<m;i++)
    	{
    		insert(&p,a[i]);
    	}
    	preorder(p);
    	printf("
    ");
    	inorder(p);
    	deleteNode(&p,9);
    	preorder(p);
    	printf("
    ");
    	inorder(p);
    	return 0;
    }
    

      

  • 相关阅读:
    delphi TMemoryStream读取html文件中文乱码
    tfrxbarcode2dview 和 tfrxbarcode not found 解决办法
    delphi ForceDirectories 用法
    Java Scanner next() 与 nextLine() 区别
    delphi 用superobject解析json
    delphi 方法可以提前声明
    delphi 判断文件是否被占用
    mysql explain用法和结果的含义
    C# SpinWait
    js异步编程
  • 原文地址:https://www.cnblogs.com/curo0119/p/8525207.html
Copyright © 2011-2022 走看看