c++實現一個二叉排序樹以及樹的遞歸遍歷的實現

二叉排序樹的理論介紹:

https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E6%8E%92%E5%BA%8F%E6%A0%91/10905079?fr=aladdin

一棵空樹,或者是具有下列性質的二叉樹

(1)若左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;

(2)若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;

(3)左、右子樹也分別爲二叉排序樹;

(4)沒有鍵值相等的結點。

二叉排序樹的節點類定義:

class node_data{
public:
	int data;//數據域
	node_data *parent, *left, *right;//每個節點有3個指針,分別指向父節點,左節點和右節點
	node_data() :data(0), parent(NULL), left(NULL), right(NULL){};//默認構造函數
	node_data(int in_data) :data(in_data), parent(NULL), left(NULL), right(NULL) {};//產生一個節點
};

二叉排序樹的類定義:

class binary_tree{
public:
	binary_tree(int num[], int len);//調用構造函數的時候,\
			就可以生成相對應大小的二叉樹,構造方法中調用的是遞歸或者非遞歸的方式生成二叉樹
	void insert_node(int data);//非遞歸的方式插入一個節點
	void insert_node_recursive(int data);//遞歸的方式插入一個節點,\
			遞歸的時候是通過調用下面private成員中的方法insert_node_recu
	void delete_node(int data);//遞歸的方式刪除一個節點及其之下的所有左右子樹的節點,\
			遞歸的時候是通過調用下面private成員中的方法delete_node_recu
	node_data *search_node(int data);//遞歸的方式查找一個節點,\
			遞歸的時候是通過調用下面private成員中的方法search_node_recu
	void print_tree(void);
private:
	node_data *root; //根節點
	void insert_node_recu(node_data *current, int data);//具體實現遞歸插入方法
	void delete_node_recu(node_data *current);//遞歸實現刪除的方法
	node_data *search_node_recu(node_data *current, int data);//data遞歸實現查找的方法
	void print_tree_ldr_recu(node_data *current);//使用遞歸的方法中序遍歷
};

二叉排序樹的插入:

對二叉排序樹的插入分爲遞歸和非遞歸的方法

binary_tree::binary_tree(int num[], int len)
{
	root = new node_data();
	for (int i = 1; i < len; i++)
	{
		insert_node(num[i]);//非遞歸的方式
		//insert_node_recursive(num[i]);//遞歸的方式
	}
}

void binary_tree::insert_node(int data)
{
	node_data *node = new node_data(data);
	node_data *p, *cur;
	p = cur = root;

	while (p != NULL)
	{
		cur = p;
		if (p->data > data){
			p = p->left;
		}
		else if (p->data < data){
			p = p->right;
		}
		else{
			delete node;
			return;
		}
	}

	node->parent = cur;
	if (cur->data > data)
		cur->left = node;
	else
		cur->right = node;
}

void binary_tree::insert_node_recursive(int data)
{
	if (root != NULL)
	insert_node_recu(root, data);//使用遞歸的操作的方法
}

void binary_tree::insert_node_recu(node_data *current, int data)
{
	if (current->data < data){//在節點current的右子樹插入
		if (current->right == NULL){//到右子樹的葉節點
			current->right = new node_data(data);//新生成節點並插入到當前節點的右節點
			current->right->parent = current;//新生成的節點的父節點是當前的節點
		}
		else{
			insert_node_recu(current->right, data);//遞歸直到葉子節點
		}
	}
	else if (current->data > data){//在節點的左子樹插入,操作同上
		if (current->left == NULL){
			current->left = new node_data(data);
			current->left->parent = current;
		}
		else{
			insert_node_recu(current->left, data);
		}
	}
}

樹的遍歷:

樹的遍歷分爲前序遍歷,中序遍歷和後序遍歷。最接單的實現方式就是遞歸的方式了。代碼如下:

void binary_tree::print_tree(void)
{
	if (root != NULL){
		//print_tree_ldr_recu(root);
		print_tree_dlr_recu(root);
		//print_tree_lrd_recu(root);
	}
}

void binary_tree::print_tree_ldr_recu(node_data *current)
{
	if (current != NULL){
		print_tree_ldr_recu(current->left);
		cout << current->data << " ";
		print_tree_ldr_recu(current->right);
	}
	
}

void binary_tree::print_tree_dlr_recu(node_data *current)
{
	if (current != NULL){
		cout << current->data << " ";
		print_tree_dlr_recu(current->left);
		
		print_tree_dlr_recu(current->right);
	}

}
void binary_tree::print_tree_lrd_recu(node_data *current)
{
	if (current != NULL){
		print_tree_lrd_recu(current->left);
		
		print_tree_lrd_recu(current->right);
		cout << current->data << " ";
	}

}

完整的測試代碼:

// ConsoleApplication1.cpp : 定義控制檯應用程序的入口點。
//

// test.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include <iostream>
#pragma warning(disable:4996)
#include <string>

using namespace std;

class node_data{
public:
	int data;//數據域
	node_data *parent, *left, *right;//每個節點有3個指針,分別指向父節點,左節點和右節點
	node_data() :data(0), parent(NULL), left(NULL), right(NULL){};//默認構造函數
	node_data(int in_data) :data(in_data), parent(NULL), left(NULL), right(NULL) {};//產生一個節點
};

class binary_tree{
public:
	binary_tree(int num[], int len);//調用構造函數的時候,\
			就可以生成相對應大小的二叉樹,構造方法中調用的是遞歸或者非遞歸的方式生成二叉樹
	void insert_node(int data);//非遞歸的方式插入一個節點
	void insert_node_recursive(int data);//遞歸的方式插入一個節點,\
			遞歸的時候是通過調用下面private成員中的方法insert_node_recu
	void delete_node(int data);//遞歸的方式刪除一個節點及其之下的所有左右子樹的節點,\
			遞歸的時候是通過調用下面private成員中的方法delete_node_recu
	node_data *search_node(int data);//遞歸的方式查找一個節點,\
			遞歸的時候是通過調用下面private成員中的方法search_node_recu
	void print_tree(void);
private:
	node_data *root; //根節點
	void insert_node_recu(node_data *current, int data);//具體實現遞歸插入方法
	void delete_node_recu(node_data *current);//遞歸實現刪除的方法
	node_data *search_node_recu(node_data *current, int data);//data遞歸實現查找的方法
	void print_tree_ldr_recu(node_data *current);//使用遞歸的方法中序遍歷
	void print_tree_dlr_recu(node_data *current);//使用遞歸的方法先序遍歷
	void print_tree_lrd_recu(node_data *current);//使用遞歸的方法後序遍歷
};

binary_tree::binary_tree(int num[], int len)
{
	root = new node_data(num[0]);
	for (int i = 1; i < len; i++)
	{
		insert_node(num[i]);//非遞歸的方式
		//insert_node_recursive(num[i]);//遞歸的方式
	}
}

void binary_tree::insert_node(int data)
{
	node_data *node = new node_data(data);
	node_data *p, *cur;
	p = cur = root;

	while (p != NULL)
	{
		cur = p;
		if (p->data > data){
			p = p->left;
		}
		else if (p->data < data){
			p = p->right;
		}
		else{
			delete node;
			return;
		}
	}

	node->parent = cur;
	if (cur->data > data)
		cur->left = node;
	else
		cur->right = node;
}

void binary_tree::insert_node_recursive(int data)
{
	if (root != NULL)
	insert_node_recu(root, data);//使用遞歸的操作的方法
}

void binary_tree::insert_node_recu(node_data *current, int data)
{
	if (current->data < data){//在節點current的右子樹插入
		if (current->right == NULL){//到右子樹的葉節點
			current->right = new node_data(data);//新生成節點並插入到當前節點的右節點
			current->right->parent = current;//新生成的節點的父節點是當前的節點
		}
		else{
			insert_node_recu(current->right, data);//遞歸直到葉子節點
		}
	}
	else if (current->data > data){//在節點的左子樹插入,操作同上
		if (current->left == NULL){
			current->left = new node_data(data);
			current->left->parent = current;
		}
		else{
			insert_node_recu(current->left, data);
		}
	}
}

node_data *binary_tree::search_node(int data)
{
	if (root != NULL)
		return search_node_recu(root, data);
	return   NULL;
}

node_data *binary_tree::search_node_recu(node_data *current, int data)//方法的思路爲,比較current中額數據和data的大小
{
	if (current->data > data){
		if (current->left == NULL)
			return NULL;
		else
			return search_node_recu(current->left, data);
	}
	else if (current->data < data){
		if (current->right == NULL)
			return NULL;
		else
			return search_node_recu(current->right, data);
	}

	return current;//相等,current就是要查找的節點
}

void binary_tree::delete_node(int data)//刪除數據爲data的節點以及它的子樹
{
	node_data *p_node = search_node(data);
	if (p_node != NULL){
		delete_node_recu(p_node);
	}
}

void binary_tree::delete_node_recu(node_data *current)
{
	if (current->left != NULL)
		delete_node_recu(current->left);
	if (current->right != NULL)
		delete_node_recu(current->right);

	if (current->parent == NULL){//current是根節點
		delete current;
		root = NULL;
		return;
	}

	//刪除葉子節點
	if (current->parent->data > current->data)//current是左節點
		current->parent->left = NULL;//將父節點的左指針NULL
	else if (current->parent->data < current->data)//同上
		current->parent->right = NULL;

	delete current;//刪除current節點
}

void binary_tree::print_tree(void)
{
	if (root != NULL){
		//print_tree_ldr_recu(root);
		print_tree_dlr_recu(root);
		//print_tree_lrd_recu(root);
	}
}

void binary_tree::print_tree_ldr_recu(node_data *current)
{
	if (current != NULL){
		print_tree_ldr_recu(current->left);
		cout << current->data << " ";
		print_tree_ldr_recu(current->right);
	}
	
}

void binary_tree::print_tree_dlr_recu(node_data *current)
{
	if (current != NULL){
		cout << current->data << " ";
		print_tree_dlr_recu(current->left);
		
		print_tree_dlr_recu(current->right);
	}

}
void binary_tree::print_tree_lrd_recu(node_data *current)
{
	if (current != NULL){
		print_tree_lrd_recu(current->left);
		
		print_tree_lrd_recu(current->right);
		cout << current->data << " ";
	}

}

int main()
{
	int num[] = {5,3,7,2,4,6,8,1};

	binary_tree my_tree(num, 8);
	cout << "ldr output: ";
	my_tree.print_tree();
	cout << endl;
	node_data *p = my_tree.search_node(6);
	cout << "search data:" << p->data << endl;
	//my_tree.print_tree();
	cout << endl;
#if 0
	my_tree.delete_node(5);
	my_tree.print_tree();
	cout << endl;
	my_tree.delete_node(6);
	my_tree.print_tree();
	cout << endl;
	my_tree.delete_node(8);
	my_tree.print_tree();
	cout << endl;
	my_tree.delete_node(8);

	my_tree.print_tree();
	cout << endl;
	my_tree.insert_node(21);
	my_tree.print_tree();
	cout << endl;
	my_tree.insert_node_recursive(6);
	my_tree.print_tree();
	cout << endl;
#endif
	return 0;
}

 

發佈了236 篇原創文章 · 獲贊 39 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章