二叉排序树

/*
二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有节点的值均小于它的根节点的值;
(2)若右子树不空,则右子树上所有节点的值均大于它的根节点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的节点。
*/

#include <iostream>
#include <algorithm>
#include <ctime>
#include <list>
using namespace std;

struct BinaryData
{
	BinaryData() :m_data(0){}
	BinaryData(int a) :m_data(a){}
	friend bool operator>(BinaryData a, BinaryData b)
	{
		return a.m_data > b.m_data;
	}
	int m_data;
};

struct BinaryNode
{
	BinaryNode(){
		memset(this, 0, sizeof(*this));
	}
	BinaryNode * lChrild;
	BinaryNode * rChrild;
	BinaryNode * father;
	BinaryData	 data;
	int nCount;
};

class BinaryTree
{
public:
	BinaryTree();
	~BinaryTree();
public:
	bool DeleteRoot(BinaryNode * &);
	bool InsertNode(BinaryData *);
	BinaryNode * FindComNode(BinaryNode *, BinaryData*);
	void FindNode(BinaryNode *&, BinaryData*, BinaryNode *&);
	bool DeleteOneNode(BinaryData *);
	bool DeleteAllNode(BinaryData *);
public:
	BinaryNode *node;
	int		nNodeCount;
};

BinaryTree::BinaryTree()
{
	nNodeCount = 0;
	node = NULL;
}


BinaryTree::~BinaryTree()
{
	if (nNodeCount > 0)
	{
		DeleteRoot(node->lChrild);
		DeleteRoot(node->rChrild);
	}
}

bool BinaryTree::DeleteRoot(BinaryNode * &n)
{
	if (n == NULL) return false;

	if (n->lChrild == NULL && n->rChrild == NULL)
	{
		delete n;
		n = NULL;
	}
	else{
		DeleteRoot(n->lChrild);
		DeleteRoot(n->rChrild);
		delete n;
		n = NULL;
	}
	return true;
}

bool BinaryTree::InsertNode(BinaryData *b)
{
	//没有元素
	if (nNodeCount == 0)
	{
		//插入根节点
		node = new BinaryNode;
		node->data = *b;
	}
	else{
		//是否已经有元素存在
		BinaryNode *has = NULL;
		FindNode(node, b, has);
		//插入相同元素
		if (has != NULL)
		{
			//元素个数+1;
			has->nCount++;
			nNodeCount++;
			return true;
		}
		//是新元素 查找插入位置的父节点
		BinaryNode *root = FindComNode(node, b);
		
		if (root != NULL)
		{
			BinaryNode *temp = new BinaryNode;
			temp->data = *b;
			if ((*b) > root->data )
			{
				root->rChrild = temp;
			}
			else{
				root->lChrild = temp;
			}
			temp->father = root;
			temp->nCount++;
			nNodeCount++;
			return true;
		}
		return false;
	}
	nNodeCount++;
	return true;
}

BinaryNode * BinaryTree::FindComNode(BinaryNode * n,BinaryData* b)
{
	if ((*b) > n->data )
	{
		if (n->rChrild == NULL)
		{
			return n;
		}
		else{
			return FindComNode(n->rChrild, b);
		}
	}
	else{
		if (n->lChrild == NULL)
		{
			return n;
		}
		else{
			return FindComNode(n->lChrild, b);
		}
	}
}


void BinaryTree::FindNode(BinaryNode *&root, BinaryData* b, BinaryNode *&result)
{
	if (root == NULL )
		return ;

	if ((root)->data.m_data == b->m_data)
	{
		result = root;
	}
	else if ((root)->data.m_data > b->m_data)
	{
		FindNode((root)->lChrild, b, result);
	}
	else{
		FindNode((root)->rChrild, b, result);
	}
}

//获得遍历列表
void GetSearchList(BinaryNode *root, list<BinaryNode *> &tempList)
{
	if (root == NULL) return;

	GetSearchList(root->lChrild, tempList);
	tempList.push_back(root);
	GetSearchList(root->rChrild, tempList);
}

//删除所有b元素
bool BinaryTree::DeleteAllNode(BinaryData *b)
{
	BinaryNode * root = NULL;
	//寻找是否b节点
	FindNode(node, b, root);
	if (root == NULL) return false;
	//删除元素个数
	int nCount = root->nCount;

	//删除节点左子树为空
	if (root->lChrild == NULL)
	{
		//有父节点
		if (root->father)
		{
			//父节点指向当前节点右子树 
			if (root->father->lChrild == root)
			{
				root->father->lChrild = root->rChrild;
			}
			else{
				root->father->rChrild = root->rChrild;
			}
		}
		else{
			//没有父节点  是根节点
			node = root->rChrild;
		}

		//当前节点有右子树
		if (root->rChrild)
		{
			//右子树指向 当前节点的父节点
			root->rChrild->father = root->father;
		}

		//删除当前节点
		delete root;
		root = NULL;

	}
	//删除节点右子树为空 左子树一定不为空 
	else if (root->rChrild == NULL)
	{
		//有父节点
		if (root->father)
		{
			//父节点指向左子树
			if (root->father->lChrild == root)
			{
				root->father->lChrild = root->lChrild;
			}
			else{
				root->father->rChrild = root->lChrild;
			}
		}
		else{
			//没有父节点  是根节点
			node = root->lChrild;
		}

		//左子树不会为空
		//if (root->lChrild)
		{
			root->lChrild->father = root->father;
		}
		//删除当前节点
		delete root;
		root = NULL;

	}
	else{
		//寻找当前节点的前驱
		BinaryNode * before = root->lChrild;
		while (before->rChrild)
		{
			before = before->rChrild;
		}

		//将前驱数据与当前节点交换  此时要删除的节点变为前驱节点
		root->data.m_data = before->data.m_data;
		root->nCount = before->nCount;


		//前驱节点的父节点指向 前驱的左子树(可能为空) 注意前驱没有右子树
		if (before->father->rChrild == before)
			before->father->rChrild = before->lChrild;
		else if (before->father->lChrild == before)
		{
			before->father->lChrild = before->lChrild;
		}

		//如果有左子树 将左字数父节点指向 前驱的父节点
		if (before->lChrild)
		{
			before->lChrild->father = before->father;
		}

		//删除前驱节点
		delete before;
		before = NULL;

	}
	nNodeCount -= nCount;
	return true;
}
bool BinaryTree::DeleteOneNode(BinaryData *b)
{
	BinaryNode * root = NULL;
	//寻找是否b节点
	FindNode(node, b, root);
	if (root == NULL) return false;
	int nCount = root->nCount;
	//元素个数减1
	root->nCount--;
	nNodeCount--;
	//元素个数为0 删除节点
	if (root->nCount == 0)
	{
		DeleteAllNode(b);
	}
	return true;
}

void Print(BinaryNode *t)
{
	if (t == NULL) return;
	Print(t->lChrild);
	for (int i = 0; i < t->nCount; i++)
	{
		cout << t->data.m_data << " ";
	}
	
	Print(t->rChrild);
}

int RAND(int a)
{
	return rand() % a;
}
int main()
{
	srand(time(NULL));

	int a[30] = {};
	BinaryTree bt;
	
	while (true)
	{
		for (int i = 20; i >= 1; i--)
		{
			a[i] = RAND(20) + 1;
		}
		random_shuffle(a + 1, a + 21, RAND);

		for (int i = 20; i >= 1; i--)
		{
			bt.InsertNode(&BinaryData(a[i]));
		}

		Print(bt.node);
		cout << endl;

		random_shuffle(a + 1, a + 21, RAND);
		for (int i = 20; i >= 1; i--)
		{
			cout << "Delete " << a[i] << endl;
			bt.DeleteOneNode(&BinaryData(a[i]));
			Print(bt.node);
			cout << endl;
		}
		Print(bt.node);
		cout << endl;
	}
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值