• “二叉查找树”学习


    查找二叉树的定义:

    image

    存储结构和二叉树相同:

    image

    需要实现的方法:

    image

    代码:

    tree.h

    #ifndef _TREE_H
    #define _TREE_H
    
    typedef int ElemType;
    
    typedef struct treenode
    {
    	ElemType data;
    	struct treenode * left;
    	struct treenode * right;
    }TREE;
    
    
    
    TREE *MakeEmptyTree();
    
    TREE *InsertTreeNode(ElemType e,TREE *t);
    
    TREE *FindTreeNode(ElemType e,TREE *t);
    
    TREE *FindMax(TREE *t);
    
    TREE *FindMin(TREE *t);
    
    TREE *DeleteTreeNode(ElemType e,TREE *t);
    
    void DeleteTree(TREE **t);
    
    #endif

    tree.c

    #include<stdio.h>
    #include<stdlib.h>
    #include"tree.h"
    
    
    TREE *MakeEmptyTree()
    {
    	return NULL;
    }
    
    TREE *InsertTreeNode(ElemType e,TREE *t)
    {
    	if(t == NULL)
    	{
    		t = (TREE *)malloc(sizeof(TREE));
    		if(t == NULL) return NULL;
    		t->data = e;
    		t->left = t->right = NULL;
    	}else if(e < t->data)
    		t->left = InsertTreeNode(e,t->left);
    	else
    		t->right = InsertTreeNode(e,t->right);
    	return t;
    }
    
    TREE *FindTreeNode(ElemType e,TREE *t)
    {
    	if(t == NULL) return NULL;
    	if(t->data == e)
    		return t;
    	else if(t->data < e)
    		return FindTreeNode(e,t->right);
    	else 
    		return FindTreeNode(e,t->left);
    }
    
    TREE *FindMax(TREE *t)
    {
    	if(t == NULL)
    		return NULL;
    	if(t->right == NULL)
    		return t;
    	return FindMax(t->right);
    }
    
    TREE *FindMin(TREE *t)
    {
    	if(t == NULL)return NULL;
    	if(t->left == NULL)
    		return t;
    	return FindMin(t->left);
    }
    
    TREE *DeleteTreeNode(ElemType e,TREE *t)
    {
    	TREE *p = NULL;
    	if(t == NULL)return NULL;
    	if(t->data > e)//数据比根小
    		t->left = DeleteTreeNode(e,t->left);//去左子树删
    	else if(t->data < e)
    		t->right = DeleteTreeNode(e,t->right);//去右子树删
    	//这个节点就是要删的
    	else if(t->left && t->right)//有两个子节点的节点
    	{
    		//找出右子树里最小的
    		p = FindMin(t->right);
    		t->data = p->data;
    		t->right = DeleteTreeNode(t->data,t->right);
    	}else//要删除的节点有一个子节点或就是叶子节点
    	{
    		p = t;
    		if(t->left == NULL)//右数有
    			t = t->right;
    		else if(t->right == NULL)
    			t = t->left;
    		free(p);
    		return t;
    	}
    	return t;
    
    }
    
    void DeleteTree(TREE **t)
    {
    	if(*t == NULL)
    		return;
    	DeleteTree(&((*t)->left));
    	DeleteTree(&((*t)->right));
    	free(*t);
    	*t = NULL;
    }

    重点解释一下删除一个节点的算法:

    包括两种情况,首先这种是要删除单子树节点的情况:

    else//要删除的节点有一个子节点或就是叶子节点
    {
    	p = t;
    	if(t->left == NULL)//右数有
    		t = t->right;
    	else if(t->right == NULL)
    		t = t->left;
    	free(p);
    	return t;
    }

    image

    这里是只有左子树,那么只要把他的左节点挂到根上面去。程序实现就是直接返回这个左节点。

    image

    image

    如果要删除的是叶子节点,比如删除上图的3,那么执行第一条语句时:

    if(t->left == NULL) t = t->right;

    就已经把t赋值为右数,第二条赋值左树,都是NULL所以最终t就是NULL,返回的也就是NULL。

    释放p,就是原来的t,就成功删除了叶子节点3.

    image

    image

    第二种情况就是要删除的是有双子树的一个节点:

    image

    else if(t->left && t->right)//有两个子节点的节点
    {
    	//找出右子树里最小的
    	p = FindMin(t->right);
    	t->data = p->data;
    	t->right = DeleteTreeNode(t->data,t->right);
    }

    我们可以找出右子树的最小的节点,当然也可以是左子树最大的节点,先把它的数据提上来,将它递归删除掉。

    image

    image

    testBSTree.c

    #include<stdio.h>
    #include"tree.h"
    
    void main()
    {
    	int n;
    	TREE *tree = MakeEmptyTree(),*p;
    	while(1)
    	{
    		printf("Please enter a num:");
    		fflush(stdin);
    		if(scanf("%d",&n) != 1)
    			break;
    		if(n == 0)
    			break;
    		tree = InsertTreeNode(n,tree);
    	}
    	printf("Max of tree is %d,min of tree is %d\n",
    		FindMax(tree)->data,FindMin(tree)->data);
    
    
    	fflush(stdin);
    	printf("Please enter search num:");
    	scanf("%d",&n);
    	if(FindTreeNode(n,tree))
    		printf("find %d\n",n);
    	else
    		printf("not find\n");
    
    	p = DeleteTreeNode(n,tree);
    	if(p)
    		printf("delete %d success\n",n);
    	else
    		printf("delete fail\n");
    
    	DeleteTree(&tree);
    	if(tree == NULL)
    		printf("delete success\n");
    	else
    		printf("fail\n");
    }

    运行时:

    image

    可以看到最大值输出76,最小值4,找到7,删除了7这个节点,进而删除了整棵树。

  • 相关阅读:
    如何给swing加上alt+x和ctrl+x快捷键
    java基础之登录程序
    RFID UHF(EPC)标签使用常识
    史密斯圆图
    C# DataTable Operations
    温度测量【RTD】
    温度测量【温度传感器类型】
    C# Debug
    c# ComboBox绑定枚举
    c# 隐藏Tab控件的标签
  • 原文地址:https://www.cnblogs.com/shenerguang/p/2336968.html
Copyright © 2020-2023  润新知