二叉搜索樹的實現(C++實現)

包含所有的二叉搜索樹的接口實現。後面博客會陸續寫出AVL樹,B樹,紅黑樹。

接口API的定義:

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>//輸入輸出流的庫
using namespace std;
#include <queue>
#include <string>

class BinarySearchTree
{
private:
	class Node
	{
	public:
		int element;
		Node * left;
		Node * right;
		Node * parent;

	public:
		Node(int element, Node * parent);

	public:
		bool isLeaf();

	public:
		bool hasTwoChildren();

	};

private:
	int m_size;
	Node * root;

public:
	BinarySearchTree();
	~BinarySearchTree();

public:

	int size();

	bool isEmpty();

	void clear();

	void add(int element);

	

	bool contains(int element);

	void preorderTravelsal();

	void inorderTravelsal();

	void postorderTravelsal();

	void levelorderTravelsal();

private:
	void postorderTravelsal(Node * node);

private:
	void inorderTravelsal(Node * node);

private:
	void preorderTravelsal(Node * node);

private:
	void elementNotNULLCheck(int element);

private:
	//返回=0 代表e1等於e2
	//返回>0 代表e1大於e2
	//返回<0 代表e1小於e2
	int compare(int e1, int e2);

public:
	void toString();
private:
	void toString(Node * node,string sb, string prefix);

public:
	int height();
private:
	int height(Node * node);


public:
	int height2();

public:
	bool isComplete();


public:
	void * predecessor(Node * node);

public:
	void * sucessor(Node * node);

public:
	void remove(int element);

private:
	void * node(int element);

private:
	void remove(Node * node);

};


接口的實現:

#include "BinarySearchTree.h"

BinarySearchTree::Node::Node(int element, Node * parent)
{
	this->element = element;
	this->parent = parent;
}

bool BinarySearchTree:: Node::isLeaf()
{
	return left == NULL && right == NULL;
}


//前驅結點
void * BinarySearchTree::predecessor(Node * node)
{
	if (node == NULL)
	{
		return NULL;
	}

	//前驅結點在左子樹中 (left->right->right->...)
	if (node->left != NULL)
	{
		Node * p = node->left;
		while (p->right != NULL)
		{
			p = p->right;
		}
		return (void *)p;
	}

	//
	while (node->parent != NULL && node == node->parent->left)
	{
		node = node->parent;
	}

	//node->parent == NULL;
	//node == node->parent->right;

	return (void*)node->parent;
}

//後繼結點
void * BinarySearchTree::sucessor(Node * node)
{
	if (node == NULL)
	{
		return NULL;
	}

	//前驅結點在左子樹中 (right->left->left->...)
	if (node->right != NULL)
	{
		Node * p = node->left;
		while (p->left != NULL)
		{
			p = p->left;
		}
		return (void *)p;
	}

	//
	while (node->parent != NULL && node == node->parent->right)
	{
		node = node->parent;
	}

	//node->parent == NULL;
	//node == node->parent->right;

	return (void*)node->parent;
}

bool BinarySearchTree::Node::hasTwoChildren()
{
	return left != NULL && right != NULL;
}

BinarySearchTree::BinarySearchTree()
{
	this->m_size = 0;
}


BinarySearchTree::~BinarySearchTree()
{

}

int BinarySearchTree::size()
{
	return this->m_size == 0;
}

bool BinarySearchTree::isEmpty()
{
	return root->element == NULL;
}

void BinarySearchTree::clear()
{
	this->root = NULL;
	this->m_size = 0;
	return;
}

void BinarySearchTree::add(int element)
{
	this->elementNotNULLCheck(element);
	if (this->root == NULL)
	{
		//添加第一個結點
		root = new Node(element, NULL);
		this->m_size++;
		return;
	}

	//添加的不是根節點
	//找到父節點
	Node * parent = this->root;
	Node * node = this->root;
	int cmp = 0;
	while (node != NULL)
	{
		cmp = compare(element, node->element);

		//保存父節點
		parent = node;

		if (cmp > 0)
		{
			node = node->right;
		}
		else if (cmp < 0)
		{
			node = node->left;
		}
		else  //相等
		{
			node->element = element;
			return;
		}
	}

	//看看插入到父節點的哪個位置
	Node * newnode = new Node(element, parent);
	if (cmp > 0)
	{
		parent->right = newnode;
	}
	else if (cmp < 0)
	{
		parent->left = newnode;
	}
	this->m_size++;
	return ;
}

void BinarySearchTree::remove(int element)
{
	remove((Node*)node(element));
}


void * BinarySearchTree::node(int element)
{
	Node * node = this->root;
	while (node != NULL)
	{
		int cmp = this->compare(element, node->element);
		if (cmp == 0)
		{
			return (void*)node;
		}
		else if (cmp > 0)
		{
			node = node->right;
		}
		else//element < node->element
		{
			node = node->left;
		}
	}
	return NULL;
}

void BinarySearchTree::remove(Node * node)
{
	if (node == NULL)
	{
		return;
	}
	this->m_size--;

	if (node->hasTwoChildren())	//度爲2
	{
		//找到後繼結點
		 Node * s = (Node*)this->sucessor(node);
		 //用後繼結點的值覆蓋度爲2的結點
		 node->element = s->element;
		 //刪除後繼結點
		 node = s;//????
	}

	//刪除node結點(node的結點 度必然是0或者1)
	Node * replacement = node->left != NULL ? node->left : node->right;
	if (replacement != NULL)//度爲1
	{
		//更改parent
		replacement->parent = node->parent;
		//更改parent的left,right的指向
		if (node->parent == NULL)
		{
			//node是度爲1的結點並且是根節點
			this->root = replacement;
		}
		else if (node == node->parent->left)
		{
			node->parent->left = replacement;
		}
		else if(node == node->parent->right)
		{
			node->parent->right = replacement;
		}
	}
	else if(node->parent == NULL)//度爲0,即葉子結點.又是根節點
	{
		this->root == NULL;
	}
	else //度爲0,即葉子結點,但不是根節點
	{
		if (node == node->parent->right)
		{
			node->parent->right = NULL;
		}
		else
		{
			node->parent->left = NULL;
		}
	}
}

bool BinarySearchTree::contains(int element)
{
	return node(element) != NULL;
}

void BinarySearchTree::elementNotNULLCheck(int element)
{
	if (element == NULL)
	{
		printf("fun elementNotNULLCheck() err\n");
		return;
	}
}


//返回=0 代表e1等於e2
	//返回>0 代表e1大於e2
	//返回<0 代表e1小於e2
int BinarySearchTree::compare(int e1, int e2)
{
	if (e1 == e2)
	{
		return 0;
	} 
	else if (e1 > e2)
	{
		return 1;
	}
	else
	{
		return -1;
	} 
}




void BinarySearchTree::inorderTravelsal()
{
	inorderTravelsal(this->root);
}

void BinarySearchTree::inorderTravelsal(Node * node)
{
	if (node == NULL)
	{
		return;
	}
	inorderTravelsal(node->left);
	cout << node->element << " ";
	inorderTravelsal(node->right);
}

void BinarySearchTree::postorderTravelsal()
{
	postorderTravelsal(this->root);
}

void BinarySearchTree::postorderTravelsal(Node * node)
{
	if (node == NULL)
	{
		return;
	}

	postorderTravelsal(node->left);
	postorderTravelsal(node->right);
	cout << node->element << " ";
}

void BinarySearchTree::levelorderTravelsal()
{
	if (this->root == NULL)
	{
		return;
	}
	queue<Node*> queue;
	queue.push(root);

	while (!queue.empty())
	{
		Node * node = queue.front();
		queue.pop();
		cout << node->element << " ";

		if (node->left != NULL)
		{
			queue.push(node->left);
		}
		
		if (node->right != NULL)
		{
			queue.push(node->right);
		}
		
	}
}


void BinarySearchTree::toString()
{
	string sb;
	toString(this->root,sb,"");
}

void BinarySearchTree::toString(Node * node,string sb,string prefix)
{
	if (node == NULL)
	{
		return;
	}

	cout << prefix<<node->element << endl;
	toString(node->left,sb, prefix +"L--");
	toString(node->right,sb, prefix+"R--");
}


void BinarySearchTree::preorderTravelsal()
{
	preorderTravelsal(this->root);
}

void BinarySearchTree::preorderTravelsal(Node * node)
{
	if (node == NULL)
	{
		return;
	}

	toString();
	cout << node->element << " ";
	preorderTravelsal(node->left);
	preorderTravelsal(node->right);
}

int BinarySearchTree::height()
{
	return height(this->root);
}

int BinarySearchTree::height(Node * node)
{
	if (node == NULL)
	{
		return 0;
	}
	return 1 + (int)max(height(node->left), height(node->right));
}


int BinarySearchTree::height2()
{
	if (this->root == NULL)
	{
		return 0;
	}

	queue<Node*> queue;
	queue.push(root);

	int rowsize = 1;
	//樹的高度
	int height = 0;
	while (!queue.empty())
	{
		Node * node = queue.front();
		queue.pop();
		rowsize--;

		if (node->left != NULL)
		{
			queue.push(node->left);
		}

		if (node->right != NULL)
		{
			queue.push(node->right);
		}

		if (rowsize == 0)	//意味着即將訪問下一層
		{
			rowsize = queue.size();
			height++;
		}
	}

	return height;
}

bool BinarySearchTree::isComplete()
{
	if (this->root == NULL)
	{
		return 0;
	}

	queue<Node*> queue;
	queue.push(root);
	bool leaf = false;

	while (!queue.empty())
	{
		Node * node = queue.front();
		queue.pop();
		if (leaf && !node->isLeaf())
		{
			return false;
		}

		if (node->left != NULL)
		{
			queue.push(node->left);
		}
		else if(node->right != NULL)
		{
			//node->left == NULL && node->right != NULL
			return false;
		}

		if (node->right != NULL)
		{
			queue.push(node->right);
		}
		else
		{
			//node->left == NULL && node->right == NULL
			//node->left != NULL && node->right == NULL
			//葉子結點

			leaf = true;
		}
	}
}


最後會進行整合。喜歡請關注,有問題留言,看到會回覆。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章