比较式查找法
基于线性表的查找法
顺序查找
逐个比较,顺序存储结构或链式存储结构
折半查找
条件:顺序存储结构,关键字有序排列
二叉判定树,查找成功时,关键字的比较次数不超过
评价:比较次数少,查找速度块,平均性能好。有序表,插入删除困难
分块查找
条件:
1、块内可以无序,块间必须有序
2、构建索引表,每个索引项对应一个块,记录该块的起始位置,以及该块中的最大关键字
ASL由两部分组成,一个是查找块(顺序或折半),另一个是在块内查找(顺序)
#include<stdio.h>
#define SIZE 20
typedef struct
{
int r[SIZE+1];
int length;
}list;
//顺序查找
int SeqSearch1(list t, int k)
{
t.r[0] = k;//监视哨
int i = t.length;
while (t.r[i] != k)
i--;
return i;//返回查找到的位置
}
int SeqSearch2(list t, int k)
{
int i = t.length;
while (i > 0 && t.r[i] != k)
i--;
return i;
}
//折半查找
int BinSearch(list t, int k)
{
int low = 1, high = t.length, mid;
while (low <= high)
{
mid = (low + high) / 2;
if (k == t.r[mid])
return mid;
else if (k < t.r[mid])
high = mid - 1;
else
low = mid + 1;
}
return 0;
}
void main()
{
list t = { {0,6,4,3,88,89,56,34,3,1,122,232,334213,3,32,232,23,789,343,45,33},20 };//结构体初始化
int k= 20;
printf("%d,%d\n", SeqSearch1(t, k), SeqSearch2(t, k));
printf("%d", BinSearch(t, k));
return;
}
基于树的查找法
二叉排序树
又称二叉查找树BST
ASL和树的形态有关,
评价:
平均性能与折半查找类似,但便于插入删除
中序遍历可以得到一个递增序列
#include<stdio.h>
#include<malloc.h>
typedef struct node
{
int data;
struct node* left, * right;
}BSTNode,*BSTree;
void InsertBST(BSTree *tree, int key)
{
BSTree t;
if (!(*tree))//递归结束条件!!!
{
t = (BSTree)malloc(sizeof(BSTNode));
t->data = key;
t->left = NULL;
t->right = NULL;
*tree = t;
}
else if (key < (*tree)->data)
InsertBST(&((*tree)->left), key);
else
InsertBST(&((*tree)->right), key);
}
void CreateBST(BSTree* tree)
{
int k;
scanf("%d", &k);
*tree = NULL;
while (k != -1)
{
InsertBST(tree, k);
scanf("%d", &k);
}
}
BSTree SearchBST1(BSTree tree, int k)//递归
{
if (!tree)
return NULL;
if (tree->data == k)//递归结束条件
return tree;
else if (tree->data > k)
SearchBST1(tree->left, k);
else
SearchBST1(tree->right, k);
}
BSTree SearchBST2(BSTree tree, int k)//非递归
{
while (tree)
{
if (k == tree->data)
return tree;
else if (k < tree->data)
tree = tree->left;
else
tree = tree->right;
}
return NULL;
}
BSTree DelBST(BSTree tree, int k)
{
BSTree p=tree, f=NULL;//f指向p的双亲结点
while (p)
{
if (p->data == k)
break;
f = p;
if (k < p->data)
p = p->left;
else
p = p->right;
}
if (!p)
return tree;//没找到
if (!(p->left))//p没有左子树
{
if (f == NULL)//p是根节点
tree = tree->right;
if (f->left == p)
f->left = p->right;
else
f->right = p->right;
free(p);
}
else//p有左子树
{
BSTree q = p, s = p->left;
while (s->right)
{
q = s;
s = s->right;
}//s为中序遍历中p的前驱结点,即p的左子树中的最右下结点
//q为s的双亲结点
if (p = q)
q->left = s->left;//s没有右子树
else
q->right = s->left;
p->data = s->data;
free(s);
}
return tree;
}
平衡二叉排序树
AVL,
平衡因子
调整方法:LL型,LR型,RR型,RL型
插入算法: 时间复杂度
B树
比较式查找法
哈希法
关键字k,存储位置p,哈希函数H,
构造哈希函数:
- 数字分析法
- 平方取中法
- 伪随机数法
- 分段叠加法:移位,折叠
- 除数求余法
假设哈希表长m,则t是小于等于m的最大素数
处理冲突:
- 开放地址法,再散列法:线性探测再散列,二次探测再散列,伪随机探测再散列
- 再哈希法:构造多个哈希函数
- 链地址法:适合经常插入、删除
- 建立公共溢出区法:基本表,溢出表
查找:线性探测再散列处理的代码
#include<stdio.h>
#define SIZE 15//哈希表长度
typedef int HashTable[SIZE];
int HashSearch(HashTable t, int k)
{
int h0 = k % 13;//除留取余fa
if (t[h0] == -1)
return -1;//没找到
else if (t[h0] == k)
return h0;
else
{
int n;
for (int i = 1; i < SIZE; i++)
{
n= (h0 + i) % 13;
if (t[n] == -1)
return -1;//没找到
else if (t[n] == k)
return ;
}
return -1;//没找到
}
}
性能分析:
装填因子=哈希表中元素个数/哈希表长度
ASL只与装填因子有关,和元素个数无关
计算和