查找算法

查找定义
查找 又称检索或查询,是指在查找表中找出满足一定条件的结点或记录对应的操作。
查找表 在计算机中,是指被查找的数据对象是由同一类型的记录构成的集合,如顺序表, 链表、二叉树和哈希表等 ;
查找效率 查找算法中的基本运算是通过记录的关键字与给定值进行比较,所以查找的效率 同常取决于比较所花的时间,而时间取决于比较的次数。通常以关键字与给定值进行比较的记录 个数的平均值来计算。
查找操作及分类
操作
1 查找某个“特定的”数据元素是否存在在查找表中
2 某个“特定的”数据元素的各种属性
3 在查找表中插入一个数据元素
4 从查找表中删除某个数据元素
分类
若对查找表只进行(1) 或(2)两种操作,则称此类查找表为静态查找表。
若在查找过程中同时插入查找表中存在的数据元素,或者从查找表中删除已存在的 某个数据元素,则称此类查找表为动态查找表

数组和索引
索引把线性表分成若干块,每一块中的元素存储顺序是任意的,但是块与块间必须按关键字 大小按顺序排列。即前一块中的最大关键字值小于后一块中的最小关键字值。
分块以后,为了快速定义块,还需要建立一个索引表,索引表中的一项对应于线性表中的一 块,索引项由键域和链域组成。键域存放相应关键字的键值,链域存放指向本块第一个节点和最 后一个节点的指针,索引表按关键字由小到大的顺序排列
分块查找的算法分两步进行,首先确定所查找的节点属于哪一块,即在索引表中查找其所在的块, 然后在块内查找待查询的数据。由于索引表是递增有序的,可采用二分查找,而块内元素是无序 的,只能采用顺序查找。(块内元素较少,则不会对执行速度有太大的影响);

二分查找
二分查找法实质上是不断地将有序数据集进行对半分割,并检查每个分区的中间元素。再重 复根据中间数确定目标范围并递归实行对半分割,直到中间数等于待查找的值或是目标数不在搜 索范围之内

#include <iostream>

//实现比较功能,返回值提供给二分查找函数调用
int int_compare(const void* key1, const void* key2) {
	const int* ch1 = (const int*)key1;
	const int* ch2 = (const int*)key2;

	return (*ch1 - *ch2);
}

//实现比较功能,返回值提供给二分查找函数调用
int char_compare(const void* key1, const void* key2) {
	const char* ch1 = (const char*)key1;
	const char* ch2 = (const char*)key2;

	return (*ch1 - *ch2);
}

//实现二分查找
int BinarySearch(void* sorted, int len, int elemSize, void* search, int(*compare)(const void* key1, const void* key2)) {
	int left = 0;
	int right = 0;
	int mid = 0;

	//初始化left和right为边界值
	left = 0;
	right = len - 1;

	//循环查找,直到左右两个边界重合
	while (left <= right) {
		int ret = 0;

		mid = (left + right) / 2;
		ret = compare((char*)sorted + (elemSize * mid), search);

		if (ret == 0) {
			//mid等于目标值,返回目标的索引值mid
			return mid;
		}
		else if (ret > 0) {
			//mid大于目标值,移动到mid的左半区查找
			right = mid - 1;
		}
		else {
			//mid小于目标值,移动到mid的右半区查找
			left = mid + 1;
		}
	}

	return -1;
}

int main(void) {
	int arr[] = { 1,3,7,9,11,15,20 };
	int search[] = { -1,0,1,7,2,11,12,20 };

	printf("整数查找测试开始:...\n");
	for (int i = 0; i < sizeof(search) / sizeof(search[0]); i++) {
		int index = BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), &search[i], int_compare);

		printf("search:%d,index:%d\n", search[i], index);
	}

	char arr1[] = { 'A','C','E','Q','X' };
	char search1[] = { '0','A','E','P','Z','X' };

	printf("字符查找测试开始:...\n");
	for (int i = 0; i < sizeof(search1) / sizeof(search1[0]); i++) {
		int index = BinarySearch(arr1, sizeof(arr1) / sizeof(arr1[0]), sizeof(char), &search1[i], char_compare);

		printf("search:%c,index:%d\n", search1[i], index);
	}

	system("pause");
	return 0;
}

在这里插入图片描述
穷举搜索
穷举法(枚举法)的基本思想是:列举出所有可能的情况,逐个判断有哪些是符合问题所要求 的条件,从而得到问题的全部解答。
它利用计算机运算速度快、精确度高的特点,对要解决问题的所有可能情况,一个不漏地进行检 查,从中找出符合要求的答案。
用穷举算法解决问题,通常可以从两个方面进行分析:
(1)问题所涉及的情况:问题所涉及的情况有哪些,情况的种数必须可以确定。把它描述 出来。应用穷举时对问题所涉及的有限种情形必须一一列举,既不能重复,也不能遗漏。重复列 举直接引发增解,影响解的准确性;而列举的遗漏可能导致问题解的遗漏。
(2)答案需要满足的条件:分析出来的这些情况,需要满足什么条件,才成为问题的答案。 把这些条件描述出来

#include <iostream>
/*有 20 枚硬币,可能包括 4 种类型:1 元、5 角、1 角和 5 分。 
已知 20 枚硬币的总价值为 10 元,求各种硬币的数量*/

int main(void) {
	int a100 = 0;//1快的硬币数量
	int a50 = 0;//5毛的硬币数量
	int a10 = 0;//1毛的硬币数量
	int a5 = 0;//5分的硬币数量

	int conut = 0;//记录可选的方案数量

	for (a100 = 0; a100 <= 10; a100++) {

		for (a50 = 0; a50 <=(1000 - a100 * 100)/50; a50++) {

			for (a10 = 0; a10 <=(1000 - a100 * 100 - a50 * 50)/10; a10++) {

				for (a5 = 0; a5 <= (1000 - a100 * 100 - a50 * 50 - a10 * 10)/5; a5++) {

					if ((a100 * 100 + a50 * 50 + a10 * 10 + a5 * 5) == 1000 && (a100 + a50 + a10 + a5) == 20) {

						std::cout <<"1块的:"<< a100 << ",5毛的:" << a50 << ",1毛的:" << a10 << ",5分的" << a5 << std::endl;
						conut++;
					}
				}//a5 end
			}//a10 end
		}//a50 end
	}//a100 end

	std::cout << conut << "种方法!" << std::endl;

	system("pause");
	return 0;
}

在这里插入图片描述
并行所搜
所谓并发是在同一实体上的多个事件同时发生。并发编程是指在在同一台计算机上“同时” 处理多个任务;
计算机就像一座工厂,时刻在运行,为人类服务。它的核心是 CPU,它承担了所有的计算任 务,就像工厂的一个现场指挥官;
任一时刻,单个 CPU 一次只能运行一个进程,此时其他进程处于非运行状态;
一个进程可以拥有多个线程,每个线程可以可以独立并行执行,多个线程共 享同一进程的资源,受进程管理;
我们要从很大的一个无序的数据集中进行搜索,假设我们的机器可以一次性容纳这么多 数据。从理论上讲,对于无序数据,如果不考虑排序,已经很难从算法层面优化了。而利用 上面我们提到的并行处理思想,我们可以很轻松地将检索效率提升多倍。具体实现思路如下: 将数据分成 N 个块,每个块由一个 线程来并行搜索

#include <iostream>
#include <Windows.h>
#include <time.h>

using namespace std;

#define TEST_SIZE (1024*1024*200)
#define NUMBER 20

typedef struct _Search {
	int* data;//搜索的数据
	size_t start;//搜索的开始位置
	size_t end;//搜索的结束位置
	size_t count;//搜索结果
}Search;

DWORD WINAPI ThreadProc(void* lpParam) {
	Search* s = (Search*)lpParam;
	time_t start;
	time_t end;

	cout << "新的线程开始执行...\n";

	time(&start);
	for (int i = 0; i < 10; i++) {
		for (size_t j = s->start; j <= s->end; j++) {

			if (s->data[i] == NUMBER) {
				s->count++;
			}
		}
	}
	time(&end);

	cout << "查找所花时间:" << end - start << endl;
	return 0;
}

int main(void) {
	
	int* data = NULL;
	int count = 0;//记录的数量
	int mid = 0;

	Search s1, s2;

	data = new int[TEST_SIZE];

	for (int i = 0; i < TEST_SIZE; i++) {
		data[i] = i;
	}

	mid = TEST_SIZE / 2;

	s1.data = data;
	s1.start = 0;
	s1.end = mid;
	s1.count = 0;

	s2.data = data;
	s2.start = mid+1;
	s2.end = TEST_SIZE-1;
	s2.count = 0;

	DWORD threadID1;//线程1的ID
	HANDLE hThread1;//线程1的句柄

	DWORD threadID2;//线程2的ID
	HANDLE hThread2;//线程2的句柄

	cout << "创建线程...\n";
	//创建线程1
	hThread1 = CreateThread(NULL, 0, ThreadProc, &s1, 0, &threadID1);

	//创建线程2
	hThread2 = CreateThread(NULL, 0, ThreadProc, &s1, 0, &threadID2);

	WaitForSingleObject(hThread1, INFINITE);
	WaitForSingleObject(hThread2, INFINITE);

	cout << "待处理的线程数量:" << s1.count + s2.count << endl;

	system("pause");
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值