• 二叉树的实现


    查找和插入的实现

    伪代码

    查找和插入的实现都用了递归的思想遍历左右子树。

    /*查找*/
    SearchBST(bt,k){
        if(bt是空||bt.key等于k)
            return bt;
        if(bt.key大于k)
            return SearchBST(bt.lchild,k) //遍历左子树
        else
            return SearchBST(bt.rchild,k) //遍历右子树
    }
    
    
    /*插入*/
    insertBST(bt,k){
        if(bt是空)
        {
            初始化bt; //创建bt新节点,并将bt的左右孩子都置为NULL
            bt->key=k;
        }
        else if(k等于bt.key) return 0; //表明bt树已存在k这个结点
        else if(k小于bt.key) return insertBST(bt->lchild, k); //遍历左子树
        else return insertBST(bt->lchild, k); //遍历右子树
    
    }
    
    
    /*创建BST树*/
    CreateBST(bt)
    {
        cin>>n>>a; //控制台获取树结点的个数n,和n个数存入数组a
        while(i小于n)       //i=0,从a[0]开始创建树bt
        {
            insertBST(bt,a[i]); //调用插入函数创建结点
            i++; 
        }
        return bt; //创建完成返回树bt
    }
    

    代码实现

    /*查找*/
    BSTNode* SearchBST(BSTNode* bt, Keytype k)
    {
    	if (bt == NULL || bt->key == k)
    		return bt;
    	if (k < bt->key)
    		return SearchBST(bt->lchild, k);
    	else
    		return SearchBST(bt->rchild, k);
    }
    
    /*创建*/
    int insertBST(BSTNode*& bt, Keytype k)
    {
    	if (bt == NULL)
    	{
    		bt = new BSTNode;
    		bt->key = k;
    		bt->lchild = bt->rchild = NULL;
    		return 1;
    	}
    	else if (k == bt->key)
    		return 0;
    	else if (k < bt->key)
    		return insertBST(bt->lchild, k);
    	else 
    		return insertBST(bt->rchild, k);
    }
    
    BSTNode* CreateBST(Keytype a[], int n)
    {
    	BSTNode* bt = NULL;
    	int i = 0;
    	while (i < n)
    	{
    		insertBST(bt,a[i]);
    		i++;
    	}
    	return bt;
    }
    

    创建BST树并中序输出结果

    运行演示

    待生成的二叉排序树的结点为:50 30 80 20 40 90 10 25 35 85 23 88,个数为12,中序排序结果为:10 20 23 25 30 35 40 50 80 85 88 90。

    运行结果正确。

    完整代码代码

    #include<iostream>
    using namespace std;
    typedef int Keytype;
    typedef int InfoType;
    typedef struct node
    {
    	Keytype key;
    	InfoType data;
    	struct node* lchild, * rchild;
    }BSTNode;
    /*创建*/
    int insertBST(BSTNode*& bt, Keytype k)
    {
    	if (bt == NULL)
    	{
    		bt = new BSTNode;
    		bt->key = k;
    		bt->lchild = bt->rchild = NULL;
    		return 1;
    	}
    	else if (k == bt->key)
    		return 0;
    	else if (k < bt->key)
    		return insertBST(bt->lchild, k);
    	else 
    		return insertBST(bt->rchild, k);
    }
    BSTNode* CreateBST(Keytype a[], int n)
    {
    	BSTNode* bt = NULL;
    	int i = 0;
    	while (i < n)
    	{
    		insertBST(bt,a[i]);
    		i++;
    	}
    	return bt;
    }
    
    /*中序输出*/
    void InOrder(BSTNode *b)
    {
    	if (b != NULL)
    	{
    		InOrder(b->lchild);
    		cout << b->key
    			<< ' ';
    		InOrder(b->rchild);
    	}
    	else return;
    }
    int main()
    {
    	BSTNode* bt;
    	int len,i=0;
    	Keytype a[50];
    	Keytype k;
    	memset(a, '0', sizeof(a));   //初始化数组
    	cout << "输入待生成的二叉排序树的结点个数:" << endl;
    	cin >> len;
    	cout << "输入二叉排序树结点:" << endl;
    	while (i<len)
    	{
    		cin >> a[i];
    		i++;
    	}
    	cout << "中序遍历二叉排序树的结果为:" << endl;
    	bt = CreateBST(a, len);
    	InOrder(bt);
    	return 0;
    }
    
    

    删除结点的实现

    思路

    删除的结点的情况分为两种:

    1. 待删除的结点只有左子树或只有右子树
    2. 待删除的结点既有左子树也有右子树

    针对情况一,若结点只有左子树,只需将待删除的结点的左子树代替待删除结点的位置;若结点只有右子树,只需将待删除的结点的右子树代替待删除结点的位置。并释放删除结点的内存空间。

    针对情况二,待删除的结点既有左子树又有右子树,找到起中序遍历结果的前驱结点的key值替代待删除的结点的key值,并释放删除前驱结点的内存空间。(所提到的前驱结点即为待删除结点的左子树的最右结点)

    伪代码

    /*删除*/
    DeleteBST(bt,k)
    {
        if(bt为空) return 0;//bt为空树,删除结点失败
        else{
            if(k小于bt.key) return DeleteBST(bt->lchild,k);//递归遍历左子树,找到待删除的结点
            else if(k大于bt.key) return DeleteBST(bt->rchild,k);//递归遍历右子树,找到待删除的结点
            else   //找到该结点了,进行删除操作
            {
                if(bt.lchild为空)
                {
                    q=bt; //q指向待删除结点
                    bt=bt->rhild;
                    free(q); //释放结点内存
                }
                else if(bt.rchild为空)
                {
                     q=bt; //q指向待删除结点
                    bt=bt->lhild;
                    free(q); //释放结点内存
                }
                else      //该节点左右孩子都有
                {
                    DeleteBST_LR(bt, bt->lchild); //调用函数
                }
            }
        }
    }
    
    /*结点有左右子树的删除*/
    DeleteBST_LR(p,r)    //p为删除的结点,r为p的左结点
    {
    	if (r->rchild不为空)
    		DeleteBST_LR(p, r->rchild);  //递归遍历找到p结点左子树的最右结点
    	else     //找到左子树的最右结点,即前驱结点
    	{
    		p->key = r->key;   //将待删除结点的key值换为前驱结点的key值
    		q = r;   
    		r = r->lchild; 
    		free(q);   //释放前驱结点的内存空间
    	}
    }
    

    具体代码

    /*结点有左右子树的删除*/
    void DeleteBST_LR(BSTNode* p, BSTNode*& r)    //p为删除的结点,r为p的左结点
    {
    	BSTNode* q;
    	if (r->rchild != NULL)
    		DeleteBST_LR(p, r->rchild);  //找到p结点左子树的最右下结点
    	else
    	{
    		p->key = r->key;
    		q = r;
    		r = r->lchild;
    		free(q);
    	}
    }
    /*删除*/
    int  DeleteBST(BSTNode*& bt, Keytype k)
    {
    	if (bt == NULL) return 0;//bt为空树,删除失败返回0
    	else {
    		if (k < bt->key)return DeleteBST(bt->lchild, k);
    		else if (k > bt->key)return DeleteBST(bt->rchild, k);
    		else {
    			BSTNode* q;
    			if (bt->lchild == NULL) {
    				q = bt;
    				bt = bt->rchild;
    				free(q);
    			}
    			else if (bt->rchild == NULL)
    			{
    				q = bt;
    				bt = bt->lchild;
    				free(q);
    			}
    			else {
    				DeleteBST_LR(bt, bt->lchild);
    			}
    			return 1;
    		}
    	}
    }
    

    运行结果展示

    创建二叉排序树“50 30 80 20 40 90 10 25 35 85 23 88”后,删除前中序遍历结果为:10 20 23 25 30 35 40 50 80 85 88 90,删除结点80后,中序遍历结果为10 20 23 25 30 35 40 50 85 88 90。

    运行结果正确。

  • 相关阅读:
    最大回文子串
    求数组中的最大连续子序列和
    如何在10亿数中找出前1000大的数
    给定一个字符串,最多删除一个字符,判断能够构成回文字符串
    HashMap(数组+链表+红黑树)、HashTable、TreeMap
    【转】jmeter如何设置登录接口只调用一次以及遇到的问题:cookie参数放在消息头headers里面
    Kafka命令行操作
    git上无法push代码解决办法
    【转】Jenkins集成Docker镜像实现自动发布
    awk命令总结
  • 原文地址:https://www.cnblogs.com/AJAJAJfighting/p/12729506.html
Copyright © 2020-2023  润新知