数据结构之查找的经典
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);
}
总结:
- 二叉排序树保留了插入和删除不用移动元素的优点
- 二叉排序树走的就是从根结点到要查找结点的路径
- 二叉排序树的查找性能取决于二叉树的形状,这就有了接下来的二叉平衡树
以上是关于数据结构之查找的经典的主要内容,如果未能解决你的问题,请参考以下文章