1. 程式人生 > >【資料結構】BST:二叉排序樹演算法

【資料結構】BST:二叉排序樹演算法

建立二叉排序樹,實現樹的插入、刪除,前、中、後序遍歷(遞迴方式)等操作。

/*****************************************   
Copyright (c) 2015 Jingshuang Hu   
   
@filename:demo.cpp   
@datetime:2015.11.03   
@author:HJS   
@e-mail:[email protected]   
@blog:http://blog.csdn.net/hujingshuang   
*****************************************/
#include <iostream>
#include "Binary_Tree.h"

using namespace std;

int main()
{
	int N = 0;
	int *data;
	cout << "N = ";
	cin >> N;
	data = (int *)malloc(N * sizeof(int));
	cout << "資料:";
	for (int i = 0; i < N; ++i)
	{
		cin >> data[i];
	}
	//30 12 54 8 24 35 70 19 28 48
	//30 12 54 24 35 70 19 28 48 37 36 38
	BT BTree;
	BTree.Create_Binary_Sort_Tree(data, N);
	while(1)
	{
		cout << "1.遍歷\t2.插入\t3.刪除\t4.退出"<<endl;
		cout <<"選擇:";
		int choice;
		cin >> choice;
		switch(choice)
		{
			case 1:
				cout << "前序:";
				BTree.Pre_Oder_Traverse(BTree.root);
				cout << endl;
				cout << "中序:";
				BTree.In_Oder_Traverse(BTree.root);
				cout << endl;
				cout << "後序:";
				BTree.Post_Oder_Traverse(BTree.root);
				cout << endl;
				break;
			case 2:
				cout << "插入:";
				int value;
				cin >> value;
				BTree.Insert_Elem(value);
				break;
			case 3:
				cout << "刪除:";
				cin >> value;
				BTree.Delete_Elem(value);
				break;
			case 4:
				return 0;
				break;
			default:
				break;
		}
	}
	return 0;
}
/*****************************************   
Copyright (c) 2015 Jingshuang Hu   
   
@filename:Binary_Tree.h   
@datetime:2015.11.03   
@author:HJS   
@e-mail:[email protected]   
@blog:http://blog.csdn.net/hujingshuang   
*****************************************/
#ifndef _BINARY_TREE_H_
#define _BINARY_TREE_H_

#include <iostream>

using namespace std;

struct Tree
{
	int elem;
	Tree *left;
	Tree *right;
};

class BT
{
public:
	BT();											//建構函式
	void Create_Binary_Sort_Tree(int *, int);		//建立二叉樹
	void Pre_Oder_Traverse(Tree *);					//前序
	void In_Oder_Traverse(Tree *);					//中序
	void Post_Oder_Traverse(Tree *);				//後序
	void Insert_Elem(int);							//插入
	void Delete_Elem(int);							//刪除
//	void Show_Tree(void);							//顯示二叉樹
//	virtual void Level_Oder_Traverse(Tree *) = 0;	//純虛擬函式
//private:
	Tree *root;
};

#endif
/*****************************************   
Copyright (c) 2015 Jingshuang Hu   
   
@filename:Binary_Tree.cpp   
@datetime:2015.11.03   
@author:HJS   
@e-mail:[email protected]   
@blog:http://blog.csdn.net/hujingshuang   
*****************************************/
#include "Binary_Tree.h"

//初始化二叉樹
BT::BT()
{
	root = NULL;
}
//建立二叉樹
void BT::Create_Binary_Sort_Tree(int *data, int N)
{
	Tree *nowfreenode = new Tree;					//生成新的節點
	Tree *prefreenode = new Tree;
	root = new Tree;
	root->elem = data[0];							//父節點元素
	root->left = root->right = NULL;				//左右孩子為空
//30 12 54 8 24 35 70 19 28 48
	for (int i = 1; i < N; ++i)
	{
		nowfreenode = root;
		Tree *newnode = new Tree;					//生成新的節點
		newnode->elem = data[i];
		newnode->left = newnode->right = NULL;

		while(nowfreenode != NULL)					//空
		{
			prefreenode = nowfreenode;				//用於記錄前一個節點
			if (newnode->elem < nowfreenode->elem)	//掛在左邊
			{
				nowfreenode = nowfreenode->left;
			}
			else
			{
				nowfreenode = nowfreenode->right;	//掛在右邊
			} 
		}
		if (newnode->elem < prefreenode->elem)
		{
			prefreenode->left = newnode;
		}
		else
		{
			prefreenode->right = newnode;
		}
	}
	delete nowfreenode;
//	delete prefreenode;
}
//前序
void BT::Pre_Oder_Traverse(Tree *T)
{
	if (T != NULL)
	{
		cout << T->elem << " ";
		Pre_Oder_Traverse(T->left);
		Pre_Oder_Traverse(T->right);
	}
}
//中序
void BT::In_Oder_Traverse(Tree *T)
{
	if (T != NULL)
	{
		In_Oder_Traverse(T->left);
		cout << T->elem << " "; 
		In_Oder_Traverse(T->right);
	}
}
//後序
void BT::Post_Oder_Traverse(Tree *T)
{
	if (T != NULL)
	{
		Post_Oder_Traverse(T->left);
		Post_Oder_Traverse(T->right);
		cout << T->elem << " ";
	}
}
//插入
void BT::Insert_Elem(int data)
{
	Tree *nowfreenode = new Tree;
	Tree *prefreenode = new Tree;
	nowfreenode = root;
	Tree *newnode = new Tree;					//生成新的節點
	newnode->elem = data;
	newnode->left = newnode->right = NULL;
	while(nowfreenode != NULL)					//空
	{
		prefreenode = nowfreenode;				//用於記錄前一個節點
		if (newnode->elem < nowfreenode->elem)	//掛在左邊
		{
			nowfreenode = nowfreenode->left;
		}
		else
		{
			nowfreenode = nowfreenode->right;	//掛在右邊
		} 
	}
	if (newnode->elem < prefreenode->elem)
	{
		prefreenode->left = newnode;
	}
	else
	{
		prefreenode->right = newnode;
	}
}
//刪除
void BT::Delete_Elem(int data)
{
	Tree *prefreenode = new Tree;
	Tree *nowfreenode = new Tree;
	nowfreenode = root;

	Tree *newnode = new Tree;
	newnode->elem = data;
	newnode->left = newnode->right = NULL;
	prefreenode = nowfreenode;
	//找到元素所在節點nowfreenode
	while((nowfreenode != NULL) && (newnode->elem != nowfreenode->elem))
	{
		prefreenode = nowfreenode;
		if (newnode->elem < nowfreenode->elem)		//往左走
		{
			nowfreenode = nowfreenode->left;
		}
		else if (newnode->elem > nowfreenode->elem)	//往右走
		{
			nowfreenode = nowfreenode->right;
		}
	}
//
	if ((nowfreenode->left != NULL) && (nowfreenode->right == NULL))//只有左子樹,用左子樹代替節點
	{	
		if ((prefreenode->left != NULL) && (prefreenode->left->elem == nowfreenode->elem))
		{
			prefreenode->left = nowfreenode->left;
		}
		else
		{
			if (prefreenode == nowfreenode)
			{
				root = nowfreenode->left;
			}
			else
			{
				prefreenode->right = nowfreenode->left;
			}
		}
	}
	else if ((nowfreenode->left == NULL) && (nowfreenode->right != NULL))//只有右子樹,用右子樹代替節點
	{
		if ((prefreenode->left != NULL) && (prefreenode->left->elem == nowfreenode->elem))
		{
			prefreenode->left = nowfreenode->right;
		}
		else
		{
			if (prefreenode == nowfreenode)
			{
				root = nowfreenode->right;
			}
			else
			{
				prefreenode->right = nowfreenode->right;
			}
		}
	}
	else if ((nowfreenode->left == NULL) && (nowfreenode->right == NULL))//是葉子節點,直接刪除
	{
		if ((prefreenode->left != NULL) && (prefreenode->left->elem == nowfreenode->elem))
			prefreenode->left = NULL;
		else
			prefreenode->right = NULL;
	}
	else//左右子樹都存在,用左子樹最右節點代替節點
	{
		prefreenode = nowfreenode;
		nowfreenode = nowfreenode->left;
		Tree *pfreenode = prefreenode;
		while(nowfreenode->right != NULL)
		{
			pfreenode = nowfreenode;
			nowfreenode = nowfreenode->right;
		}
		prefreenode->elem = nowfreenode->elem;
		pfreenode->right = nowfreenode->left;
		delete prefreenode;
	}
//	delete nowfreenode;
}