数据结构学习——二叉搜索树BST相关代码(c++实现)

二叉搜索树的c++实现


#include<windows.h>
#include<iostream>
using namespace std;

typedef int DataType;

struct node{

public:
	node() :key(0),
		left(nullptr),
		right(nullptr),
	    father(nullptr)
	{}

	node(int k, node* a, node* b, node* c)
		:key(k),
		left(a),
		right(b),
		father(c)
	{}


	DataType key;
	struct node* left;
	struct node* right;
	struct node* father;
};

typedef struct node node;
typedef struct node* pnode;

插入操作

class BST{
	//typedef struct node node;
//	typedef struct node* pnode;

public:
	BST() :root(nullptr)
	{}

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
node* insert_bstree(int key){
	
		node *z;    // 新建结点
		// 如果新建结点失败,则返回。
		if ((z = new node(key, NULL, NULL, NULL)) == NULL)
			return root;
	
		insert(root, z);
	}


void insert(pnode& root, pnode z){                              //测试形参能不能用  pnode root
	pnode y = NULL;
	pnode x = root;

	// 查找z的插入位置
	while (x != NULL)
	{
		y = x;
		if (z->key < x->key)
			x = x->left;
		else
			x = x->right;
	}

	z->father = y;
	if (y == NULL)
	{
		root = z;                //这里对 因为root 进行了操作   
	}
		
	else if (z->key < y->key)
		y->left = z;
	else
		y->right = z;

}

遍历操作

void preOrder()
{
	preOrder(root);
}
void inOrder()
{
	inOrder(root);
}
void postOrder()
{
	postOrder(root);

}


	
void preOrder(pnode root) 
{
	if (root != NULL)
	{
		cout << root->key << " ";
		preOrder(root->left);
		preOrder(root->right);
	}
}


void inOrder(pnode root) const
{
	if (root != NULL)
	{
		inOrder(root->left);
		cout << root->key << " ";
		inOrder(root->right);
	}
}

void postOrder(pnode root) const
{
	if (root != NULL)
	{
		postOrder(root->left);
		postOrder(root->right);
		cout << root->key << " ";

	}
}

查找操作

pnode BST_search(pnode root, int key)const{
	if (root == NULL || root->key == key)
		return root;

	if (key < root->key)
		return BST_search(root->left, key);
	else
		return BST_search(root->right, key);


}

//查找指定key的节点
pnode search(int key) const {

	return BST_search(root, key);

}

//查找最大节点值

int max_search(){

 pnode node= _max(root);
 return node->key;
}

pnode _max(pnode root){

	if (root == nullptr)
		return root;

	while (root->right != NULL)
		root = root->right;
	return root;

}



//查找最小节点值

int min_search(){

	pnode node = _min(root);
	return node->key;
}

pnode _min(pnode root){

	if (root == nullptr)
		return root;

	while (root->left != NULL)
		root = root->left;
	return root;

}

//查找节点的前驱节点

pnode pre_node(pnode x){

	// 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。
	if (x->left != NULL)
		return _max(x->left);

	// 如果x没有左孩子。则x有以下两种可能:
	// (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
	// (01) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
	pnode y = x->father;
	while ((y != NULL) && (x == y->left))
	{
		x = y;
		y = y->father;
	}	

	return y;


}


//查找节点的后继节点
pnode post_node(pnode x){

	// 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。
	if (x->right != NULL)
		return _min(x->right);

	// 如果x没有右孩子。则x有以下两种可能:
	// (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。
	// (02) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。
    pnode y = x->father;
	while ((y != NULL) && (x == y->right))
	{
		x = y;
		y = y->father;
	}

	return y;
}

删除操作

思路:
找到需要删除的节点之后,关于节点删除的规则如下: 
1. 如果该节点是叶子节点,直接删除该节点即可。 
2. 如果该节点不是叶子节点,但是只有左孩子或者右孩子的话,先交换该节点与其左孩子或者右孩子的值,然后删除其左孩子或者右孩子。 
3. 如果该节点既有左孩子,又有右孩子的话,可以采用如下方式进行调整(这里对该节点的右子树进行调整,左子树调整同理) 
(1)先新建一个指针,指向要删除节点的右孩子。 
(2)由于右孩子可能本身存在左孩子,即delNode->right->left != NULL,而delNode->right->left->val是小于delNode->right->val的,所以直接向delNode->right->val赋值给要删除的节点是不可取的,因此要先要找到删除节点的右子树中的最小节点,即递归判断删除节点的右孩子的左孩子是否存在。 
(3)找到删除节点右子树的最小节点minRNode,将其与要删除的节点delNode交换取值,然后删除minRNode

```c
TreeNode* deleteNode(TreeNode* root, int key) {
        if(root == NULL)
            return NULL;
        if(root->val == key){
            if(root->left != NULL && root->right != NULL){
                TreeNode* minRNode = root->right;
                while(minRNode->left != NULL)
                    minRNode = minRNode->left;
                root->val = minRNode->val;
                root->right = deleteNode(root->right, minRNode->val);
            }
            else{
                if(root->left != NULL){ //仅有左孩子
                    root->val = root->left->val;
                    delete(root->left);
                }
                else if(root->right != NULL){   //仅有右孩子
                    root->val = root->right->val;
                    delete(root->right);
                }
                else{   //无孩子
                    delete(root);
                }

            }
            return root;
        }
        if(key > root->val)
            root->right = deleteNode(root->right, key);
        else if(key < root->val)
            root->left = deleteNode(root->left, key);
        return root;
    }

## 销毁操作
```c
void destroy(pnode*& root){

if(!root)
return;

if(!root->left)
 destroy(root->left);

if(!root->right)
 destroy(root->right);

delete root;
root=NULL;

}



void destroy(){

destroy(root);

}

打印操作

//二叉树的打印
void print(){

	if (root != nullptr)
	{
		print(root,root->key,0);
	}


}
void print(pnode root, int key, int direction){

	if (root != NULL)
	{
		if (direction == 0)    // tree是根节点
			cout <<  root->key << " is root" << endl;
		else                // tree是分支节点
			cout <<  root->key << " is "  << key << "'s "  << (direction == 1 ? "right child" : "left child") << endl;

		print(root->left, root->key, -1);
		print(root->right, root->key, 1);
	}

}

/////////////
private:
	pnode root;

};

测试代码


int main(){
	
	//1.测试形参能不能用 ? pnode(&) root
	//2.c++版本遍历的参数写法?  


	BST* tree=new BST();
	int arr[] = { 1, 5, 4, 3, 2, 6 };
	for (int i = 0; i<6; i++)
    {
		cout << arr[i] << " ";
        tree->insert_bstree(arr[i]);
    }
	

	cout << "\n== 前序遍历: ";
	tree->preOrder();
	
    cout << "\n== 中序遍历: ";
    tree->inOrder();
	
	cout << "\n== 后序遍历: ";
	tree->postOrder();
	
	cout << endl;

	//查找指定值
	tree->search(5);

	//查找最大值和最小值
	cout << tree->max_search() << endl;;
	cout << tree->min_search() << endl;

	//查找前驱和后继
	//节点的前驱:是该节点的左子树中的最大节点。
	//节点的后继:是该节点的右子树中的最小节点。




	//删除节点

	//打印节点
	tree->print();
    //销毁节点





	system("pause");
	return 0;
}

结果:
在这里插入图片描述

建造好的树的结构就是这个样子:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/tonglin12138/article/details/91909005