C++——算法基础之动态查找表1——二叉排序树

二叉排序树的简单操作:

(1)查找,——类似于二分查找(较简单,略)

(2)插入,——若新结点已存在,则不插入;否则,插入(较简单,略)

(3)删除,——由于结点的删除会对树造成影响;所以,我们重点谈谈。

分类:

1)删除的结点为叶子结点  ——   直接删除,然后使其  = NULL

2)删除的结点为单孩子结点  ——   让其双亲结点指向它的孩子结点,然后使其  = NULL

2)删除的结点为双孩子结点  ——   

方法一:让其左孩子代替它,其右孩子接在其左孩子的最右端

1,,可通过修改结点的值来实现——>前提:递归比较6

2,可通过修改指针来实现——>比较符合初学者

方法二:让其右孩子的最左端代替它,这个最左端的右孩子代替这个最左端。

坑点:1,当删除叶子结点时,应在主树中将其置为空,否则在遍历时会出现异常。

    2,当获取某个结点的值时,在不确定的情况下,需判断其是否为空。

下面结合图和代码仔细研读(图有点烂哈)




#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <functional>
#include <algorithm>
#include <numeric>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <cstring>
#include <conio.h>
using namespace std;

#define NULL 0

struct bstnode
{
	int key;
	bstnode *lchild, *rchild;
};

bstnode *root = NULL;			//根结点
bstnode *parent = NULL;			//待插入位置的双亲结点

int bstsearch (int key)
{
	struct bstnode *ps;
	int mark;			//查找标志:0->空树;1->查找成功;2->查找失败,应插入到左子树中;3->查找失败,应插入到右子树中
	if(!root)
	{
		mark = 0;
	}
	else
	{
		ps = root;
		while(ps)
		{
			if(ps->key == key)
			{
				mark = 1;
				break;
			}
			else if(ps->key > key)
			{
				parent = ps;
				ps = ps->lchild;
				mark = 2;
			}
			else
			{
				parent = ps;
				ps = ps->rchild;
				mark = 3;
			}
		}
	}
	return mark;
}

int bstinsert (int key)
{
	bstnode *point;
	int mark, flag;				//falg:0-》插入 1-》未插入
	mark = bstsearch (key);
	if(1 == mark)
	{
		flag = 1;
	}
	else
	{
		point = (bstnode *)malloc (sizeof (bstnode));
		if(!point)
		{
			cout << "Memory overflow!";
			_getch ();
			exit (0);
		}
		point->key = key;
		point->lchild = NULL;
		point->rchild = NULL;
		if(mark == 0)
		{
			root = point;
			flag = 0;
		}
		else if(mark == 2)
		{
			parent->lchild = point;
			flag = 0;
		}
		else
		{
			parent->rchild = point;
			flag = 0;
		}
	}
	return flag;
}

void bst_inorder (bstnode *point)
{
	if(point)
	{
		bst_inorder (point->lchild);
		cout << "  " << point->key;
		bst_inorder (point->rchild);
	}
}

//修改值
int bstdelete (bstnode ** del_root, int key)
{
	bstnode *ps, *left;
	if(*del_root == NULL)			//二叉树为空
	{
		return 0;
	}
	else
	{
		if(key < (*del_root)->key)		//待删除结点在左子树
		{
			cout << "left\t";
			_getch ();
			return bstdelete (&(*del_root)->lchild, key);
		}
		if(key > (*del_root)->key)		//待删除结点在右子树
		{
			cout << "right\t";
			_getch ();
			return bstdelete (&(*del_root)->rchild, key);
		}
		ps = *del_root;										//找到待删除结点
		if(ps->lchild == NULL && NULL == ps->rchild)		//待删除结点为叶子结点
		{
			*del_root = NULL;
			free (ps);
			return 1;
		}
		if(ps->lchild == NULL)								//待删除结点只有右子树
		{
			*del_root = (*del_root)->rchild;
			free (ps);
			return 1;
		}
		if(ps->rchild == NULL)								//待删除结点只有左子树
		{
			*del_root = (*del_root)->lchild;
			free (ps);
			return 1;
		}
		else
		{
			if((*del_root)->lchild->rchild == NULL)
			{
				(*del_root)->key = (*del_root)->lchild->key;
				return bstdelete (&ps->lchild, (*del_root)->key);
			}
			left = ps->lchild;
			while(left->rchild != NULL)
			{
				ps = left;
				left = left->rchild;
			}
			(*del_root)->key = left->key;
			return bstdelete (&ps->rchild, (*del_root)->key);
		}
	}
}

//修改指针1					//还需修改
int bstdelete2 (int key)
{
	if(!root)
	{
		return 0;
	}
	int flag = bstsearch (key);				//判断root中是否存在key
	if(1 != flag)
	{
		return 0;
	}
	bstnode *ps = root;
	if(ps->key == key)									//当删除结点为根结点时
	{
		if(ps->lchild == NULL && ps->rchild == NULL)
		{
			free (ps);
			root = NULL;
			ps = NULL;
			return 1;
		}
		if(ps->lchild == NULL)
		{
			root = ps->rchild;
			free (ps);
			ps = NULL;
			return 1;
		}
		if(ps->rchild == NULL)
		{
			root = ps->lchild;
			free (ps);
			ps = NULL;
			return 1;
		}
		else
		{
			root = ps->lchild;
			bstnode *pCur = ps->lchild;
			while(pCur->rchild)
			{
				pCur = pCur->rchild;
			}
			pCur->rchild = ps->rchild;
			free (ps);
			ps = NULL;
			return 1;
		}		
	}
	else									//当删除结点不为根结点时
	{
		while(key != ps->key)				//找到待删除结点
		{
			parent = ps;					//parent为待删除结点的双亲结点
			if(key < ps->key)
			{
				ps = ps->lchild;
			}
			else
			{
				ps = ps->rchild;
			}
		}
		if(ps->lchild == NULL && ps->rchild == NULL)				//待删除结点为叶子结点
		{
			if(parent->lchild != NULL && parent->lchild->key == key)
			{
				parent->lchild = NULL;
			}
			else
			{
				parent->rchild = NULL;
			}
			free (ps);
			ps = NULL;
			return 1;
		}
		if(ps->lchild == NULL)					//待删除结点只含有右子树
		{
			if(parent->lchild != NULL && parent->lchild->key == ps->key)		//判断待删除结点为双亲结点的哪个孩子
			{
				parent->lchild = ps->rchild;
			}
			else
			{
				parent->rchild = ps->rchild;
			}
			free (ps);
			ps = NULL;
			return 1;
		}
		if(ps->rchild == NULL)								//待删除结点只含有左子树
		{
			if(parent->lchild != NULL && parent->lchild->key == ps->key)
			{
				parent->lchild = ps->lchild;
			}
			else
			{
				parent->rchild = ps->lchild;
			}
			free (ps);
			ps = NULL;
			return 1;
		}
		else							//待删除结点既有右子树又有左子树
		{
			if(parent->lchild != NULL && parent->lchild->key == ps->key)
			{
				parent->lchild = ps->lchild;
			}
			else
			{
				parent->rchild = ps->lchild;
			}
			bstnode *pCur = ps->lchild;
			while(pCur->rchild)
			{
				pCur = pCur->rchild;
			}
			pCur->rchild = ps->rchild;
			free (ps);
			ps = NULL;
			return 1;	
		}		
	}
}

//修改指针2
int bstdelete3 (int key)
{
	if(!root)
	{
		return 0;
	}
	int flag = bstsearch (key);
	if(1 != flag)
	{
		return 0;
	}
	bstnode *ps = root;
	if(key == ps->key)					//待删除结点为根结点
	{
		if(ps->lchild == NULL && ps->rchild == NULL)
		{
			free (ps);
			root = NULL;
			ps = NULL;
			return 1;
		}
		else if(ps->lchild == NULL)
		{
			root = ps->rchild;
			free (ps);
			ps = NULL;
			return 1;
		}
		else if(ps->rchild == NULL)
		{
			root = ps->lchild;
			free (ps);
			ps = NULL;
			return 1;
		}
		else
		{
			bstnode *pCur = ps->rchild;
			if(pCur->lchild == NULL)				//待删除结点的右子树没有左子树
			{
				pCur->lchild = ps->lchild;
				root = pCur;
				free (ps);
				return 1;
			}
			else
			{
				while(pCur->lchild)
				{
					parent = pCur;					//parnet为欲取代待删除结点的双亲结点
					pCur = pCur->lchild;
				}
				root = pCur;
				if(parent->lchild != NULL && parent->lchild->key == pCur->key)
				{
					parent->lchild = pCur->rchild;
				}
				else
				{
					parent->rchild = pCur->rchild;
				}
				pCur->lchild = ps->lchild;
				pCur->rchild = ps->rchild;
				free (ps);
				ps = NULL;
				return 1;
			}			
		}
	}
	else								//待删除结点为非根结点
	{
		while(key != ps->key)
		{
			parent = ps;				//parent为待删除结点的双亲结点
			if(key < ps->key)
			{
				ps = ps->lchild;
			}
			else
			{
				ps = ps->rchild;
			}
		}
		if(ps->lchild == NULL && ps->rchild == NULL)
		{
			if(parent->lchild != NULL && parent->lchild->key == key)
			{
				parent->lchild = NULL;
			}
			else
			{
				parent->rchild = NULL;
			}
			free (ps);
			ps = NULL;
			return 1;
		}
		else if(ps->lchild == NULL)
		{
			if(parent->lchild != NULL && parent->lchild->key == key)
			{
				parent->lchild = ps->rchild;
			}
			else
			{
				parent->rchild = ps->rchild;
			}
			free (ps);
			ps = NULL;
			return 1;
		}
		else if(ps->rchild == NULL)
		{
			if(parent->lchild != NULL && parent->lchild->key == key)
			{
				parent->lchild = ps->lchild;
			}
			else
			{
				parent->rchild = ps->lchild;
			}
			free (ps);
			ps = NULL;
			return 1;
		}
		else
		{
			bstnode *pCur = ps->rchild;					//pCur为欲取代结点
			bstnode *pPre = NULL;						//pPre为欲取代结点的双亲结点
			if(pCur->lchild == NULL)
			{
				if(parent->lchild != NULL && parent->lchild->key == key)
				{
					parent->lchild = pCur;
				}
				else
				{
					parent->rchild = pCur;
				}
				pCur->lchild = ps->lchild;
				free (ps);
				return 1;
			}
			else
			{
				while(pCur->lchild)
				{
					pPre = pCur;
					pCur = pCur->lchild;
				}
				if(parent->lchild != NULL && parent->lchild->key == key)
				{
					parent->lchild = pCur;
				}
				else
				{
					parent->rchild = pCur;
				}
				if(pPre->lchild != NULL && pPre->lchild->key == pCur->key)
				{
					pPre->lchild = pCur->rchild;
				}
				else
				{
					pPre->rchild = pCur->rchild;
				}
				pCur->lchild = ps->lchild;
				pCur->rchild = ps->rchild;
				free (ps);
				ps = NULL;
				return 1;
			}			
		}
	}
}

int main()
{
	int kx, falg;
	cout << "\n This is bin_sort_tree_insert...";
	while(true)
	{
		cout << "\n\n pelease input the key want to insert('0' to exit):";
		cin >> kx;
		if(kx == 0)
		{
			break;
		}
		falg = bstinsert (kx);
		if(1 == falg)
		{
			cout << "\n\tFound ! And " << kx << "has been int the tree.";
		}
		else
		{
			cout << "\n\t Not found ! And " << kx << "has been inserted into the tree.";
		}
	}
	cout << "\n The bin_sort_tree is : \n";
	bst_inorder (root);
	while(true)
	{
		cout << "\n\n please input the key want to delete:";
		cin >> kx;
		falg = bstdelete3 (kx);
		if(1 == falg)
		{
			cout << "\n\n\t" << kx << " has been deleted.......";
		}
		else
		{
			cout << "\n\t Failure!";
		}
		cout << "\n\n The bin_sort_tree is :\n";
		bst_inorder (root);
		cout << endl;
	}	
	return 0;
}


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值