Data structure, search algorithm (binary, block, hash)

1. Search algorithm

        1. Binary search: (precondition: must be an ordered sequence)

#include <stdio.h>
//二分查找 value代表的是被查找的值
int findByHalf(int *p, int n, int value)
{
	int low = 0;//low低
	int high = n-1;//high高
	int middle;//用来保存中间位置的下标
	while(low <= high)//注意此处循环结束的条件,需要加上 =
	{
		//不断获取中间位置的下标
		middle = (low + high) / 2;
		if(value < p[middle])//说明在前半段,移动high
		{
			high = middle-1;
		}
		else if(value > p[middle])//说明在后半段,移动low
		{
			low = middle + 1;
		}
		else//对应p[middle] == value 情况
		{
			return middle;
		}
	}
	return -1;//代表没有找到
}


int main(int argc, const char *argv[])
{
	int a[] = {12,34,56,77,89,342,567,7898};
	int i;
	for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)//把数组中的每个元素都找一遍,进行测试程序
	{
		printf("%d post is %d\n",a[i],findByHalf(a,sizeof(a)/sizeof(a[0]),a[i]));
	}
	//查找10000返回 -1
	printf("%d post is %d\n",10000,findByHalf(a,sizeof(a)/sizeof(a[0]),10000));
	return 0;
}

2. Block search: (ordered between blocks, disordered within blocks)

    Index table + source data table

    Ideas:

    (1) First determine which block in the index table

    (2) Then traverse this block to search

//Index table
typedef struct 
{     int max; //The maximum value in the block     int post;//The starting position subscript of the block, post array subscript }index_t; //Index //Source data table int a[19] = {18, 10, 9, 8, 16, 20, 38, 42, 19, 50, 84, 72, 56, 55, 76, 100, 90, 88, 108}; 0 5 10 15 //Index                              table index_t b [4] = { {18,0},{50,5},{84,10},{108,15}};



    




#include <stdio.h>
//索引表
typedef  struct 
{
	int max; //块中最大值
	int post;//块的起始位置下标,post数组下标
}index_t; //索引
	
//a原数据表 index_list 索引表 value 被查找的值
int findByBlock(int *a, index_t *index_list,int value)
{
	//start和end作为源数据表的下标取搜索
	int start;//保存起始下标
	int end;//终止下标的后一个位置
	//1.思想,先确定value在哪一块中,遍历索引表与每块中的最大值进行比较
	int i;
	for(i = 0; i < 4; i++)
	{
		if(value <= index_list[i].max)//说明value有可能在i块中
		{
			//确定当前i块中的起始下标和终止
			start = index_list[i].post;
			//假设value在最后一块中,i+1数组越界,所以end的赋值,需要进行条件判断
			if(i == 3)//说明在最后一个块
			{
				end = 19;
			}
			else 
			{
				end = index_list[i+1].post;
			}
			break;//注意此处一定要有break
		}
	}
	//确定块的起点和终点后,对源数据表进行遍历
	for(i = start; i < end; i++)
	{
		if(a[i] == value)
			return i;
	}
	return -1;
}
	

int main(int argc, const char *argv[])
{
	int i;
	//源数据表
	int a[19] = {18, 10, 9, 8, 16, 20, 38, 42, 19, 50, 84, 72, 56, 55, 76, 100, 90, 88, 108};
	//			 0              4  5                   10                  15
	//索引表,结构体数组
	index_t index_list[4] = {
   
   {18,0},{50,5},{84,10},{108,15}};
	for(i = 0; i < 19; i++)//把源数据表中的每一个数据查询一遍,测试程序
	{
		printf("%d post is %d\n",a[i],findByBlock(a,index_list,a[i]));
	}
	printf("%d post is %d\n",22,findByBlock(a,index_list,22));
	
	return 0;
}

3. Hash table (hash hash function)

    hash storage

    There is a table that saves the relationship between the keywords in the data and the corresponding storage locations

    When selecting a key, select a keyword that is not repeated in the data as the key

    When saving, save according to the corresponding relationship

    Take according to the corresponding relationship

####Exercise 1####

    //Save data age + population corresponding to age  
    
    10 100
    20 300

    Enter the age and population, save it in the hash table according to the corresponding relationship,
    
    enter the age to be queried, and print out the population of that age

 

        3.1 Direct address method


#include <stdio.h>

//哈希函数,代表了数据中的关键字与存储位置之间的关系
//调用哈希函数能够得到数据的存储位置
int hashFun(int key)
{
	int post = key-1;//key-1代表关系 post通过关系得到存储位置
	return post;
}

//存储数据到哈希表,存的时候按照对应的关系存
void saveAgeNum(int *hash_list,int key,int num)
{
	//1.通过key得到数据存储的位置,调用哈希函数 
	int post = hashFun(key);
	//2.将数据存储到哈希表中
	hash_list[post] = num;
}
//从哈希表中取数据,取的时候按照对应的关系取
int getAgeNum(int *hash_list,int key)
{
	//1.通过key得到数据存储的位置,调用哈希函数 
	int post = hashFun(key);
	//2.将数据取出 
	return hash_list[post];
}
int main(int argc, const char *argv[])
{
	int i;
	int age,num;//年龄和对应年龄的人口数
	int hash_list[200] = { 0 };//哈希表,用来保存年龄和对应年龄的人口数,之所以长度为200,暂定人的寿命为200岁
	for(i = 0; i < 4; i++)
	{
		printf("请您输入年龄和年龄对应的人口数:\n");//输入四组数据保存到哈希表中
		scanf("%d %d",&age,&num);
		//将输入的数据保存到哈希表中
		saveAgeNum(hash_list,age,num);
	}
	//进行查找对应年龄的人口数
	for(i = 0; i < 6; i++)
	{
		printf("请您输入要查询的年龄:\n");
		scanf("%d",&age);
		printf("%d: %d人\n",age,getAgeNum(hash_list,age));
	}
	
	return 0;
}

        3.2 Reserved remainder method

    See code demo below

    The number of data is n

    n = 11

    The length of the hash table m = n/a //n stores the number of data a is the filling factor, the most reasonable between 0.7-0.8

    m = 11 / 0.75 == 15 The largest index between 0-15 is 13

    //prime prime number is a prime number not greater than the table length

   // keep remainder method

  int hashFun(int key)
    {
        int post = key % prime; //key % 13
        return post;
    }

        3.3 Open Address Method//Resolve conflicts generated during hash storage

    When a conflict occurs, fill in the data by finding a vacancy in the array, instead of using the hash function to get the array subscript

        3.4 Methods for resolving conflicts

                (1) Linear exploration method 

#include <stdio.h>
//哈希函数 
int hashFun(int key)
{
	int post = key % 13;//取余13的原因是因为 选不大于哈希表长的最大质数
	return post;
}
//哈希查找
int hashSearch(int *hash_list,int key)
{
	int d = 1;//d 取值 1 2 3 4 5 当冲突发生的时候采用一次线性探查法
	int post;//用来保存存储位置
	int remnum;//用来保存余数
	post = remnum = hashFun(key);
	while(d < 15 && hash_list[post] != 0 && hash_list[post] != key)
	{
		//采用一次线性探查法
		post = (remnum + d) % 15;
		d++;
	}
	if(d >= 15)
		return -1;//代表表已经溢出
	return post;
	//hash_list[post] == 0//意味着当前post这个位置可以存放数据,初始化哈希表所有位置全为0,代表没有存放数据
	//hash_list[post] == key //意味着当前表中的key已经存在
}
//向哈希表中存储数据 
void hashSave(int *hash_list, int key)
{
	//先通过key获取存储位置,对key存储位置进行判断
	int post = hashSearch(hash_list,key);
	if(post == -1 || hash_list[post] == key)
	{
		printf("表溢出或key已经存在!!!\n");
		return;
	}
	//将数据存储到哈希表中 
	hash_list[post] = key;
}

int main(int argc, const char *argv[])
{
	int i;
	int a[11] = {23,34,14,38,46,16,68,15,7,31,26};
	int hash_list[15] = { 0 };//哈希表长度为15 因为 数据长度n / 装填因子a  11 / 0.75,装填因子通常采用0.7-0.8之间最为合理
	//将数据全部保存到哈希表中
	for(i = 0; i < 11; i++)
	{
		hashSave(hash_list,a[i]);
	}
	//打印哈希表 
	for(i = 0; i < 15; i++)
	{
		printf("%d ",hash_list[i]);
	}
	printf("\n");
	return 0;
}

        (2) Chain address method 

#include <stdio.h>
#include <stdlib.h>

typedef struct node_t  
{
	int key;
	struct node_t *next;
}link_node_t,*link_list_t;

//哈希函数
int hashFun(int key)
{
	int post = key % 13;
	return post;
}

link_list_t hashSearch(link_list_t *hash_list,int key)
{
	link_list_t h = NULL;//用来保存无头链表的头指针
	//1.先通过key调用哈希函数获取位置
	int post = hashFun(key);//需要将判断key放入第条链表
	h = hash_list[post];//h指向key对应存储位置的那条链表
	while(h != NULL && h->key != key)//相当于遍历无头链表,同时检查key
	{
		h = h->next;
	}
	return h;
	//h == NULL 说明没找到key可以进行存储
	//h != NULL h->key == key 说明key已经存在
}

//存储数据
void hashSave(link_list_t *hash_list,int key)
{
	int post = hashFun(key);
	link_list_t pnew = NULL;//用来保存新创建的节点
	link_list_t p = hashSearch(hash_list,key);
	if(p == NULL)//key不存在,可以进行插入数据
	{
		//1.创建一个新的节点用来保存key 
		pnew = (link_list_t)malloc(sizeof(link_node_t));
		if(NULL == pnew)
		{
			perror("pnew malloc failed");
			return;
		}
		//2.将key保存到新节点中
		pnew->key = key;
		pnew->next = NULL;
		//3.将新的节点插入到对应存储位置的链表中,将新节点每次插入无头链表头的位置
		pnew->next = hash_list[post];
		hash_list[post] = pnew;
	}
	else
	{
		printf("key已经存在了!!!\n");
	}
}


int main(int argc, const char *argv[])
{
	int i;
	link_list_t h = NULL;//临时保存每条链表的头
	int a[11] = {23,34,14,38,46,16,68,15,7,31,26};	
	//hash_list是一个结构体指针数组,每一个元素都是结构体指针
	link_list_t hash_list[13] = { 0 };//为什么长度是13,因为保留余数法每次%13 得到的位置在0-12之间
	//将所有的key保存起来
	for(i = 0; i < 11; i++)
	{
		hashSave(hash_list,a[i]);
	}
	//遍历哈希表 有13条链表
	for(i = 0; i < 13; i++)//hash_list中保存的是13条无头链表的头指针
	{
		printf("%d:",i);
		h = hash_list[i];
		while(h != NULL)//相当于遍历无头链表
		{
			printf("%d ",h->key);
			h = h->next;
		}
		printf("\n");
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_52119661/article/details/132437554