数据结构之查找的经典

Posted ~千里之行,始于足下~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构之查找的经典相关的知识,希望对你有一定的参考价值。

数据结构_查找


顺序表查找

  • 顺序查找算法
/*顺序表查找*/
int sequentialSearch1(int * a, int n, int key)
{
	for (int i = 1; i <= n; i++)
	{
		if (a[i] == key)
		{
			return i;
		}
	}
	return 0;
}
  • 顺序查找算法的优化
/*顺序表查找的优化(带哨兵)*/
int sequentialSearch2(int * a, int n, int key)
{
	int i = n;
	a[0] = key;
	while (a[i] != key)
	{
		i--;
	}
	return i;
}

注: 哨兵解决了每次比较之后需要判断位置是否越界,提高了效率


有序表查找

  • 二分查找
/*二分查找*/
int binarySearch(int * a, int n, int key)
{
	int low = 1;
	int high = n;
	int mid = 0;
	while (low <= high)
	{
		mid = low + (high - low) >> 2;//防止溢出
		if (a[mid] < key)
		{
			low = mid + 1;
		}
		else if (a[mid] > key)
		{
			high = mid - 1;
		}
		else
			return mid;
	}
	return 0;
}
  • 插值查找

插值查找: mid = low + (key- a[low]) / (a[high] - a[low]) * (high - low)
适用于数据比较密集的查找操作

  • 斐波那契查找

线性索引查找

  • 稠密索引
  • 分块索引
    块内无序,块间有序 (块内使用顺序查找,块间使用二分查找)
  • 倒排索引

二叉排序树

  • 二叉树的存储结构
/*二叉树的二叉链表结构定义*/
typedef struct BiTNode
{
	int data;
	struct BiTNode * lChild;
	struct BiTNode * rChild;
}BiTNode, * BiTree;
  • 二叉排序树的插入(插入前先查找)
/*递归查找二叉排序T树中是否存在数据key*/
/*f指向双亲,初始调用值未NULL*/
/*查找成功时p指向找到的结点*/
/*查找失败时p指向访问的最后一个结点*/

bool searchBST(BiTree T, int key, BiTree f, BiTree * p)
{
	if (!T)       //查找不成功
	{
		*p = f;
		return false;
	}
	else if (key == T->data)  //查找成功
	{
		*p = T;
		return true;
	}
	else if (key < T->data)
	{
		return searchBST(T->lChild, key, T, p);
	}
	else
	{
		return searchBST(T->rChild, key, T, p);
	}
}

/*二叉排序树的插入*/
bool insertBST(BiTree * T, int key)
{
	BiTree p, s;
	if (!searchBST(*T, key, NULL, &p))
	{
		s = (BiTree)malloc(sizeof(BiTNode));
		s->data = key;
		s->lChild = s->rChild = NULL;

		if (!p)
		{
			*T = s;  //插入s为根结点
		}
		else if (key < p->data)
		{
			p->lChild = s;
		}
		else
		{
			p->rChild = s;
		}

		return true;
	}
	else
		return false;
}
  • 二叉排序树的删除
//依赖p的前驱结点删除
bool delF(BiTree * p)
{
	BiTree q, s;

	if (NULL == (*p)->rChild)//右子树为空
	{
		q = *p;
		*p = (*p)->lChild;
		//free(q);
	}
	else if (NULL == (*p)->lChild)//左子树为空
	{
		q = *p;
		(*p) = (*p)->rChild;
		free(q);
	}
	else
	{
		q = *p;
		s = (*p)->lChild;
		while (s->rChild) //找到p的前驱结点s,q为s的双亲结点
		{
			q = s;
			s = s->rChild;
		}

		(*p)->data = s->data;

		if (q != *p)
		{
			q->rChild = s->lChild;
		}
		else
		{
			q->lChild = s->lChild;
		}
		free(s);
	}

	return true;
}

//依赖p的后继结点删除
bool delR(BiTree * p)
{
	BiTree q, s;

	if (NULL == (*p)->rChild)//右子树为空
	{
		q = *p;
		*p = (*p)->lChild;
		//free(q);
	}
	else if (NULL == (*p)->lChild)//左子树为空
	{
		q = *p;
		(*p) = (*p)->rChild;
		free(q);
	}
	else
	{
		q = *p;
		s = (*p)->rChild;
		while (s->lChild) //找到p的前驱结点s,q为s的双亲结点
		{
			q = s;
			s = s->lChild;
		}

		(*p)->data = s->data;

		if (q != *p)
		{
			q->lChild = s->rChild;
		}
		else
		{
			q->rChild = s->rChild;
		}
		free(s);
	}

	return true;
}

bool deleteBST(BiTree * T, int key)
{
	if (!*T) //找不到
	{
		return false;
	}
	else  
	{
		if (key == (*T)->data) //找到要删除的结点
		{
			return delR(T);
		}
		else if (key < (*T)->data)
		{
			deleteBST(&(*T)->lChild, key);
		}
		else
		{
			deleteBST(&(*T)->rChild, key);
		}
	}
}
  • 二叉树的遍历
/*中序遍历*/
void InorderBST(BiTree T)
{
	if (!T)
	{
		return;
	}
	InorderBST(T->lChild);
	printf("%d ", T->data);
	InorderBST(T->rChild);

}

总结:

  • 二叉排序树保留了插入和删除不用移动元素的优点
  • 二叉排序树走的就是从结点到要查找结点的路径
  • 二叉排序树的查找性能取决于二叉树的形状,这就有了接下来的二叉平衡树

以上是关于数据结构之查找的经典的主要内容,如果未能解决你的问题,请参考以下文章

java实现二分查找

一文学懂经典算法系列之:折半查找(附讲解视频)

一文学懂经典算法系列之:顺序查找(附讲解视频)

经典算法系列之:二分查找

经典算法系列之:二分查找

五大经典算法思想之分治策略