BinarySearchTree

本文详细介绍了BinarySearchTree类,包括Node结构体、核心函数如search_ptr、swap、递归和迭代查找、获取最小值/最大值、前驱/后继、插入和删除操作,以及遍历方法(先序、中序和后序)。
摘要由CSDN通过智能技术生成

1、 struct Node

代码

struct Node{
	//节点的构造函数 
	Node(int& k, int& val): key(k), value(val), parent(NULL), left_child(NULL), right_child(NULL) { }
	
	//成员变量声明 
	int key;
	int value;
	Node* parent;
	Node* left_child;
	Node* right_child;
};

内容

Node结构体成员包括:

  • key :key值
  • value : value值
  • *parent : 父节点
  • *left_child : 左子节点
  • *right_child : 右子节点

2、class BinarySearchTree

(1) search_ptr()函数:返回x的指针

代码

Node* BinarySearchTree::search_ptr(int k){  //返回 k 所在的指针 
	Node* ptr = root;
	while(ptr){  //从根节点向下寻找
		if(k == ptr->key) return ptr;  //寻找到,返回指针 
		if(k < ptr->key) ptr = ptr->left_child;
		if(k > ptr->key) ptr = ptr->right_child;
	}
}

(2) swap()函数:交换两个节点信息

代码

void BinarySearchTree::swap(Node*& a, Node*& b){  //交换两个节点 
	int temp;
	
	temp = a->key;  //交换key值 
	a->key = b->key;
	b->key = temp; 
	
	temp = a->value;  //交换value值 
	a->value = b->value;
	b->value = temp;
}

(3) search_recursion()函数:递归查找

代码

int BinarySearchTree::search_recursion(int& x, int k){  //递归查找
	Node* xptr = search_ptr(x);
	if(k == xptr->key) return xptr->value;  //寻找到,返回对应的value值 
	else{
		if(k < xptr->key && xptr->left_child != NULL){  //key值小,且仍有左子节点 
			x = xptr->left_child->key;  //以左子节点为根向下寻找 
			search_recursion(x, k);
		}
		else if(k > xptr->key && xptr->right_child != NULL){  //key值大,且仍有右子节点
			x = xptr->right_child->key;  //以右子节点为根向下寻找 
			search_recursion(x, k);
		}
		else return -1;  //若无对应的左右子节点,不在树中,返回-1 
	}
}

(4) search_iterative()函数:迭代查找

代码

int BinarySearchTree::search_iterative(int x, int k){  //迭代查找
	Node* xptr = search_ptr(x);
	while(xptr){  //从x节点向下寻找 
		if(k == xptr->key) return xptr->value;  //寻找到,返回对应的value值 
		if(k < xptr->key) xptr = xptr->left_child;
		else if(k > xptr->key) xptr = xptr->right_child;
	}
	return -1;  //未找到,返回-1 
}

思路

两个查找的思路都是:比较key值,向下传递指针。


(5) minimum() maximum()函数:最小值/最大值

代码

int BinarySearchTree::minimum(int x){  //最小值 
	Node* xptr = search_ptr(x);
	while(xptr->left_child) xptr = xptr->left_child;  //不断寻找左子节点到底 
	return xptr->value;
}

int BinarySearchTree::maximum(int x){  //最大值 
	Node* xptr = search_ptr(x);
	while(xptr->right_child) xptr = xptr->right_child;  //不断寻找右子节点到底 
	return xptr->value;
}

思路

最小/最大值,从当前节点,不断向下寻找左/右子节点即可。


(6) predecessor() successor()函数:前驱/后继

代码

int BinarySearchTree::predecessor(int x){  //前驱 
	Node* xptr = search_ptr(x);
	if(xptr->left_child){  //如果有左子节点 
		xptr = xptr->left_child;  //以该点为根,寻找该点下的最大值 
		while(xptr->right_child) xptr = xptr->right_child;  //不断寻找右子节点直至到底 
	}
	else{  //如果没有左子节点
		while(xptr->parent != NULL && xptr != xptr->parent->right_child){  //如果有父节点,且该点是其左子节点,继续往上寻找 
			xptr = xptr->parent;
		}
		xptr = xptr->parent;  //前驱为当前指向点的父节点 
		if(!xptr) return -1;  //如果为空,不存在前驱,返回-1 
	}
	return xptr->value;
}

int BinarySearchTree::successor(int x){  //后继 
	Node* xptr = search_ptr(x);
	if(xptr->right_child){  //如果有右子节点
		xptr = xptr->right_child;  //以该点为根,寻找该点下的最小值
		while(xptr->left_child) xptr = xptr->left_child;  //不断寻找左子节点直至到底 
	}
	else{  //如果没有右子节点
		while(xptr->parent != NULL && xptr != xptr->parent->left_child){  //如果有父节点,且该点是其右子节点,继续往上寻找 
			xptr = xptr->parent;
		}
		xptr = xptr->parent;  //后继为当前指向点的父节点
		if(!xptr) return -1;  //如果为空,不存在后继,返回-1
	}
	return xptr->value;
}

思路

  • 前驱:以左子节点为根,向下寻找最大值。
  • 后继:以右子节点为根,向下寻找最小值。

(7) insert_x()函数:插入

代码

void BinarySearchTree::insert_x(Node*& xptr, int k, int val){  //插入 
	if(!xptr){  //如果该点为空,将节点信息存入此处 
		xptr = new Node(k, val);
		return;
	}
	if(k < xptr->key){  //如果小,从左子节点继续往下 
		if(xptr->left_child == NULL){
			xptr->left_child = new Node(k, val);
			xptr->left_child->parent = xptr;
			return;
		}
		else insert_x(xptr->left_child, k, val);
	}
	else if(k > xptr->key){  //如果大,从右子节点继续往下
		if(xptr->right_child == NULL){
			xptr->right_child = new Node(k, val);
			xptr->right_child->parent = xptr;
			return;
		}
		else insert_x(xptr->right_child, k, val);
	}
}

思路

从根节点开始,不断比较key值:

  • k比当前点key值小,向下找左子节点
  • k比当前点key值大,向下找右子节点

直到找到最底,不存在对应子节点后,创建新的Node,将信息key value *parent存入。


(8) delete_x()函数:删除

代码

void BinarySearchTree::delete_x(int k){  //删除 
	Node* ptr = search_ptr(k);
	if(ptr->left_child && ptr->right_child){  //如果左右子节点均存在 
		Node* ptr1 = search_ptr(successor(k));
		swap(ptr, ptr1);
		ptr = ptr1;
	}
	
	else if(ptr->left_child == NULL && ptr->right_child == NULL){  //如果左右子节点都为空 
		Node* ptr2 = ptr->parent;
		if(ptr2->left_child == ptr) ptr2->left_child = NULL;
		else if(ptr2->right_child == ptr) ptr2->right_child = NULL;
		delete ptr;
	}
	
	else if(!(ptr->left_child) && (ptr->right_child)){  //左为空,右非空 
		Node* ptr3 = ptr->parent;
		ptr->right_child->parent = ptr3;
		if(ptr3->left_child == ptr) ptr3->left_child = ptr->right_child;
		else if(ptr3->right_child == ptr) ptr3->right_child = ptr->right_child;
		delete ptr;
	}
	
	else if((ptr->left_child) && !(ptr->right_child)){  //左非空,右为空 
		Node* ptr4 = ptr->parent;
		ptr->left_child->parent = ptr4;
		if(ptr4->left_child == ptr) ptr4->left_child = ptr->left_child;
		else if(ptr4->right_child == ptr) ptr4->right_child = ptr->left_child;
		delete ptr;
	}
	return;
}

思路

讨论左右子节点空与非空共四种情况:

  • 均非空: 找前驱或后继代替该点即可。
  • 均为空: 只需要将父节点对应的子节点指针改为空即可。
  • 左空,右非空: 将右子节点代替该点即可。
  • 左非空,右空: 与上一种情况类似。

(9) traversal()函数:遍历

代码

void BinarySearchTree::traversal_preorder(Node* ptr){  //先序:根左右 
	if(!ptr) return;
	cout << ptr->value << " ";
	traversal_preorder(ptr->left_child);
	traversal_preorder(ptr->right_child);
	return;
}

void BinarySearchTree::traversal_inorder(Node* ptr){  //中序:左根右 
	if(!ptr) return;
	traversal_inorder(ptr->left_child);
	cout << ptr->value << " ";
	traversal_inorder(ptr->right_child);
	return;
}

void BinarySearchTree::traversal_postorder(Node* ptr){  //后序:左右根 
	if(!ptr) return;
	traversal_postorder(ptr->left_child);
	traversal_postorder(ptr->right_child);
	cout << ptr->value << " ";
	return;
}

void BinarySearchTree::traversal(){  //遍历全树
	traversal_preorder(root);
	cout << endl; 
	traversal_inorder(root);
	cout << endl;
	traversal_postorder(root);
	cout << endl;
}

思路

  • 先序:根左右
  • 中序:左根右
  • 后序:左右根

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值