Linux C 数据结构—查找

一.查找概述

顺序查找: 编程简单。数据量不太多时,数据没有顺序。
折半查找: 必须是有序数据。 效率较高,比较次数少。
分块查找: 块内无序、块间有序。 块间查找可以使用顺序或者折半查找。 块内顺序查找。
哈希查找: key - value. 通过运算,将值与所在位置建立联系,通过这样的方式,可以快速的查找数据。
实现方法:直接地址/平方取中法/叠加法/质数除余法。
在哈希表中,不可避免出现冲突,如何解决:开放地址法/备用表法/线性探查法/链地址法

二.顺序查找

适用范围: 数据无序,数据量不大的情况。

//练习:编写函数,实现功能:在一个数组中,有20个数据,在此数据中,找到是否有88这样一个数据。

#include <stdio.h>
int find_data(int *p,int n,int value)
{
	int i;
	for(i=0; i<n; i++)
	{
		if(p[i] == value)
			return i+1;
	}
	return 0;
}
int main()
{
	int a[] = {2,88,4,5,6,7,7,78,899,6,4,2211,3,566,345,8,22,123,42,6};
	int n = find_data(a,20,88);
	if(n)
		printf("Find it!\n");
	else 
		printf("No \n");
}

三.折半查找

适用: 数据有序。

#include <stdio.h>
int find_by_half(int *p,int n,int value)
{
	int low = 0,high = n-1,mid;
	while(low <= high)
	{
		mid =( low + high )/2;       //找中点。
		if(value < p[mid])           //判断大小。 共三种情况。 小于、大于、等于。
		{
			high = mid - 1;
		}
		else if(value > p[mid])
		{
			low = mid + 1;
		}
		else
		{
			return mid+1;
		}
	}
	return -1;
}
int main()
{
	int a[] = {3,12,18,20,30,40,50,60,70,88,99,100};
	int n = find_by_half(a,12,20);
	if(n == -1)
		printf("Not find\n");
	else 
		printf("Find it ! position :%d\n",n);
}

四.分块查找

特点: 块内无序、块间有序
查找方法: 先找索引表,后对应到数据中的一块位置。
分块查找,有两个表:
索引表。
原始数据表。

#include <stdio.h>
typedef struct 
{
	int max;
	int pos;
}index_t;       
//通过索引表查找数据。 
int find_by_index(int *p,index_t *t,int value)
{
	int i,start = 0,end = 0;
	for(i=0; i<4; i++)
	{
		if(value <= t[i].max)
		{
			start = t[i].pos-1;    //数据在原始表中的起始下标(位置-1)。 
			if(i == 3)
				end = 19;          //数据在原始表中的终止位置
			else 
				end = t[i+1].pos;
			break;         //找到数据所在块之后,要及时退出当前循环。 
		}
	}
	for(i=start; i<end; i++)       //根据找到的起止位置,在原始表中查找数据。顺序查找即可。 
	{
		if(value == p[i])
		{
			return i;    //返回的是下标。 
		}
	}
	return -1;
}
int main()
{
	int a[] = {18,10,9,8,16,20,38,42,19,50,84,72,56,55,76,100,90,88,108};
	index_t b[4] = {{18,1},{50,6},{84,11},{108,16}};
	int n = find_by_index(a,b,42);
	if(n == -1)
		printf("Not find \n");
	else 
		printf("Pos : %d\n",n+1);   //下标值 + 1 = 位置。 
}

五.Hash表(又称为散列表)

将表里的数据与其位置建立对应关系。(value-key)
存取数据: 按同样的规则去存取即可。

方法一: 直接地址法。 示例如下:

#include <stdio.h>
int hash_func(int key)   //哈希函数,用来建立规则。
{
	return  key-1;
}
void save_hash(int *p,int age,int value)   //使用哈希规则存数据。 
{
	int index = hash_func(age);
	p[index] = value;
}
int find_by_hash(int *p,int age)   //使用规则取数据。 
{
	int pos = hash_func(age);
	return p[pos];
}
int main()
{
	int a[100] = {0};

	int age,num;
	while(1)
	{
		puts("Input age num: ");
		scanf("%d%d",&age,&num);
		if(age == 0)
			break;
		save_hash(a,age,num);      //存。 
	}

	puts("Search :input age :");
	scanf("%d",&age);              //取。 
	num = find_by_hash(a,age);

	printf("The num is %d\n",num);
}

方法二: 叠加法: 示例如下:

#include <stdio.h>
int hash_func(int num)
{
	int x = num/10000-num/100%100+num%100;
	return x;
}
void save_hash(int *p,int num)
{
	int index = hash_func(num);
	p[index] = num;
}
int find_by_hash(int *p,int num)
{
	int pos = hash_func(num);
	return p[pos];
}
int main()
{
	int num[] = {566765,434322,896756,214657,113565,558867};
	int a[1000] = {0};
	int i;
	for(i=0; i<sizeof(num)/sizeof(int); i++)
	{
		save_hash(a,num[i]);
	}

	puts("Search num:");
	scanf("%d",&i);
	int res = find_by_hash(a,i);
	if(res == 0)
		printf("Not find\n");
	else 
		printf("I find it !\n");
	return 0;
}

方法三: 质数除余法: 示例如下:

注意的点:

  1. 根据数据的个数,确定要创建的哈希表长。 (n/X) x 填装因子:一般是 0.75.([11/0.75]=15 )
  2. 确定的质数,要符合的条件: 比表长小的最大的质数。 例如:表长15,选取的质数:13.

如果产生冲突,使用的方法:
备用表法。
开放地址法。
线性探查法。(顺延)(二次探查等)

#include <stdio.h>
int hash_func(int num)
{
	return num%13;
}
void save_by_zhi(int *b,int *c,int num)
{
	static int index = 0;
	int pos = hash_func(num);	
	if(b[pos] == 0)
	{
		b[pos] = num;
	}
	else
	{
		c[index] = num;
		index++;
	}
	return ;
}

void  find_by_zhi(int *b,int *c,int num)
{
	int i ;
	int pos = hash_func(num);
	if(b[pos] == num)
	{
	 	printf("Find it!  Pos :B: %d\n",pos);
		return ;
	}
	else 
	{
		for(i=0; i<5; i++)
		{
			if(c[i] == num)
			{
			 	printf("Find it!  Pos :C: %d\n",i);
				return ;	
			}
		}
		printf("Not found!\n");
	}
	return ;
}
int main()
{
	int a[] = {23,13,46,77,45,32,8,92,73,75,40};
	int b[15] = {0};
	int c[5] = {0};

	int i;
	for(i=0; i<11; i++)
		save_by_zhi(b,c,a[i]);

	int number;
	puts("Search num:");
	scanf("%d",&number);
	find_by_zhi(b,c,number);
}

hash查找: 直接地址法。 key-value
叠加法。
质数除余法。 n/0.75 = 30, p=29

六. 练习

一个字符串中可能包含a-z中的多个字符,字符也可能重复,例如char a[] = “dfafdafdafdfdffefdf”;
写一个程序,对于给定一个这样的字符串,求出字符串中出现次数最多的那个字母以及出现的次数
(若次数最多的字母有多个,则全部求出)。

#include <stdio.h>
int main()
{
	char s[] = "qfdjfgqoyfwqadfqp";
	int num[26] = {0};
	int i = 0,max = 0;

	while(s[i] != '\0')    //统计字母出现的次数。 num[0]--> 'a'  num[1]--> 'b' , ...
	{
		num[s[i]-'a']++;
		i++;
	}
	for(i=0; i<26; i++)    //获取出现的最大值。 
	{
		if(max < num[i])
			max = num[i];
	}
	for(i=0; i<26; i++)    //出现次数最多,且次数相同的字母,及对应出现的次数。 
	{
		if(num[i] == max)
			printf("%c : %d\n",i+'a',max);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值