常见查找算法

比较式查找法

基于线性表的查找法

顺序查找

逐个比较,顺序存储结构或链式存储结构

ASL_{succ}=\frac{(n+1)}{2}

折半查找

条件:顺序存储结构,关键字有序排列

二叉判定树,查找成功时,关键字的比较次数不超过\left \lfloor \log_{2}{n} \right \rfloor+1

ASL_{succ}\approx \log_{2}{(n+1)}-1

评价:比较次数少,查找速度块,平均性能好。有序表,插入删除困难

分块查找

条件:

1、块内可以无序,块间必须有序

2、构建索引表,每个索引项对应一个块,记录该块的起始位置,以及该块中的最大关键字

ASL由两部分组成,一个是查找块(顺序或折半),另一个是在块内查找(顺序)

#include
#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和树的形态有关,ASL=O(\log_{2}{n})

评价:

平均性能与折半查找类似,但便于插入删除

中序遍历可以得到一个递增序列

#include
#include
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,ASL=O(\log_{2}{n})

平衡因子

调整方法:LL型,LR型,RR型,RL型

插入算法: 时间复杂度O(\log_{2}{n})

B树

比较式查找法

哈希法

关键字k,存储位置p,哈希函数H, p=H(k)

构造哈希函数:

  1. 数字分析法
  2. 平方取中法
  3. 伪随机数法
  4. 分段叠加法:移位,折叠
  5. 除数求余法p=H(k)=k%t  假设哈希表长m,则t是小于等于m的最大素数

 处理冲突:

  1. 开放地址法,再散列法:线性探测再散列,二次探测再散列,伪随机探测再散列
  2. 再哈希法:构造多个哈希函数
  3. 链地址法:适合经常插入、删除
  4. 建立公共溢出区法:基本表,溢出表

查找:线性探测再散列处理的代码

#include
#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只与装填因子有关,和元素个数无关

计算ASL_{succ}ASL_{unsucc}

你可能感兴趣的:(数据结构,c语言)