二叉排序樹的理論介紹:
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;
}