二分查找法及二分搜索树及其C++实现

二分查找法及二分搜索树及其C++实现

  • 二分查找法
    • 二分查找简介
    • 二分查找的实现
  • 二分搜索树
    • 二分搜索树简介
    • 二分搜索树的实现

二分查找法

二分查找简介

二分查找是一种在每次比较之后将查找空间一分为二的算法。每次需要查找集合中的索引或元素时,都应该考虑二分查找。如果集合是无序的,我们可以总是在应用二分查找之前先对其进行排序。
二分查找一般由三个主要部分组成:
1.预处理:如果集合未排序,则进行排序。
2.二分查找:使用循环或递归在每次比较后将空间划分为两半。
3.后处理:在剩余空间确定可行的候选者。
二分查找的时间复杂度为O(log(n))。

二分查找的实现

#include<vector>
#include<assert.h>
using namespace std;
template<typename T>
int binaryserach(vector<T> vec,T target)
{
	int n = vec.size();
	if(n == 0)
		return -1;
	int l = 0;
	int r = n - 1;
	while (l <= r)
	{
		int mid = l + (r - l) / 2;//使用这种形式可以避免int类型的溢出
		if (vec[mid] == target)
			return mid;
		if (vec[mid] < target)
			l = mid + 1;
		if (vec[mid] > traget)
			r = mid - 1;
	}
	return -1; //查找失败则返回-1
}

二分搜索树

二分搜索树简介

二分搜索树(BST)是二叉树的一种特殊表现形式,满足如下特性:

  1. 每个节点中的值必须大于(或等于)存储在其左子树中的任何值。
  2. 每个节点中的值必须小于(或等于)存储在其右子树中的任何值。
    二分查找法及二分搜索树及其C++实现_第1张图片
    二分搜索树的查找、插入、删除操作的时间复杂度均为O(log(n))。

二分搜索树的实现

此二分搜索树为不含重复键值的实现方式,若需要重复键值,可在相应实现细节处将小于条件改成小于等于或者将大于改成大于等于。

#ifndef BST_H
#define BST_H
#include<assert.h>
#include<iostream>
#include<queue>
using namespace std;
template<typename Key, typename Value>
class BST
{
public:
	BST() : root(nullptr),count(0) {}
	~BST() //析构函数
	{
		destroy(root);
	}
	int size() //返回二分搜索树中节点数量
	{
		return count;
	}
	bool empty() //判断二分搜索树是否为空
	{
		return count == 0;
	}
	void insert(Key key, Value value) //在树中插入一个节点
	{
		root = insert(root, key, value);
	}
	bool contain(Key key) //判断当前树中是否包含该键值
	{
		return contain(root, key);
	}
	Value* serach(Key key) //在树中寻找指定键值,并返回该键值出的存储值
	{
		return serach(root, key);
	}
	void preOrder() //前序遍历树
	{
		preOrder(root);
	}
	void inOrder() //中序遍历树
	{
		inOrder(root);
	}
	void postOrder() //后序遍历树
	{
		postOrder(root);
	}
	void levelOrder() //层序遍历树
	{
		queue<Node*> qu;
		qu.push(root);
		while (!qu.empty())
		{
			Node* tmp = qu.front();
			qu.pop();
			cout << tmp->key << endl;  //执行打印键值操作,可执行其他操作
			if(tmp->left!=nullptr)
				qu.push(tmp->left);
			if(tmp->right!=nullptr)
				qu.push(tmp->right);
		}
	}
	Key maxkey() //返回数中最大键值
	{
		assert(count != 0);
		Node* maxNode = maxkey(root);
		return maxNode->key;
	}
	Key minkey() //返回树中最小键值
	{
		assert(count != 0);
		Node * minNode = minkey(root);
		return minNode->key;
	}
	void removeMin() //删除树中最小键值
	{
		if (root)
			root = removeMin(root);
	}
	void removeMax() //删除树中最大键值
	{
		if (root)
			root = removeMax(root);
	}
	void remove(Key key) //删除树中指定键值 
	{
		root = remove(root, key);
	}
private:
	struct Node  //二分搜索树节点定义
	{
		Key key;
		Value value;
		Node* left;
		Node* right;
		Node(Key key,Value value) : key(key),value(value),left(nullptr),right(nullptr) {}   //节点构造函数
		Node(Node* node) : key(node->key),value(node->value),left(node->left),right(node->right) {} //节点构造函数
	};
	Node* root; //二分搜索树根结点
	int count; //二分搜索树中节点数量
	//以下为相应的递归辅助函数
	void destroy(Node* node)
	{
		if (node == nullptr)
			return;
		destroy(node->left);
		destroy(node->right);
		delete node;
		count--;
	}
	Node* insert(Node* node, Key key, Value value)
	{
		if (node == nullptr)
		{
			Node* newnode = new Node(key, value);
			count++;
			return newnode;
		}
		if (key < node->key)
			node->left = insert(node->left, key, value);
		if (key > node->key)
			node->right = insert(node->right, key, value);
		if (key == node->key)
			node->value = value;
		return node;
	}
	bool contain(Node* node, Key key)
	{
		if (node == nullptr)
			return false;
		if (node->key == key)
			return true;
		if (node->key < key)
			return contain(node->right, key);
		if (key < node->key)
			return contain(node->left, key);
	}
	Value* serach(Node* node, Key key)
	{
		if (node == nullptr)
			return nullptr;
		if (node->key == key)
			return &(node->value);
		if (node->key < key)
			return serach(node->right, key);
		if (key < node->key)
			return serach(node->left, key);
	}
	void preOrder(Node* node)
	{
		if (node == nullptr)
			return;
		cout <<  node->key << endl; //执行打印键值操作,可执行其他操作
		preOrder(root->left);
		preOrder(root->right);
	}
	void inOrder(Node* node)
	{
		if (node == nullptr)
			return;
		inOrder(node->left);
		cout << node->key << endl; //执行打印键值操作,可执行其他操作
		inOrder(node->right);
	}
	void postOrder(Node* node)
	{
		if (node == nullptr)
			return;
		postOrder(node->left);
		postOrder(node->right);
		cout << node->key << endl; //执行打印键值操作,可执行其他操作
	}
	Node* maxkey(Node* node)
	{
		if (node->right == nullptr)
			return node;
		return maxkey(node->right);
	}
	Node* minkey(Node* node)
	{
		if (node->left == nullptr)
			return node;
		return minkey(node->left);
	}
	Node* removeMin(Node* node)
	{
		if (node->left == nullptr)
		{
			Node* rightnode = node->right;
			delete node;
			count--;
			return rightnode;
		}
		node->left = removeMin(node->left);
		return node;
	}
	Node* removeMax(Node* node)
	{
		if (node->right == nullptr)
		{
			Node* leftnode = node->left;
			delete node;
			count--;
			return leftnode;
		}
		node->right = removeMax(node->right);
		return node;
	}
	Node* remove(Node* node, Key key)
	{
		if (node == nullptr)
			return node;
		if (node->key < key)
		{
			node->right = remove(node->right, key);
			return node;
		}
		else if (key < node->key)
		{
			node->left = remove(node->left, key);
			return node;
		}
		else
		{
			if (node->left == nullptr)
			{
				Node* rightnode = node->right;
				delete node;
				count--;
				return rightnode;
			}
			if (node->right == nullptr)
			{
				Node* leftnode = node->left;
				delete node;
				count--;
				return leftnode;
			}
			Node* newnode = new Node(minkey(node->right));
			count++; //创建了一个新结点先将节点数量+1,因为下一步的删除指定子树最小节点的函数会将节点数量-1
			newnode->right = removeMin(node->right);
			newnode->left = node->left;
			delete node;
			count--;
			return newnode;
		}
	}
};
#endif

你可能感兴趣的:(数据结构与算法)