两种高效的查找算法

目录:

1:并行搜索

2:二分查找

二分查找的实现是建立在有序的数组之上的,只有有序的数组才能准确找到要查找元素在数组中的位置,所以在测试二分查找的正确性时要用有序的数组,并行搜索我们这做的是查找一个元素在数组中出现的次数,所以不用是一个有序的数组,这两种算法都很高效接下来就为大家介绍这两种算法。

1:并行搜索,什么是并行顾名思义就是两个程序函数同时执行,在以往的算法中我们编写的函数在主函数中都是一个函数执行结束接着执行另外一个函数,而并行是在主函数中两个函数同时执行,那么怎么实现并行呢?这里就要引入进程,线程,什么是进程呢?每一个进程都有自己独立的数据空间,进程之间的切换会有较大的数据开销,一个进程可以包含多个线程,例如(我们 cpu 里面同时运行QQ,微信 这两个程序的运行就是两个进程),什么是线程?线程就是例如:我们运行QQ时我们可以在QQ里面和朋友聊天也可以和刷动态,聊天和刷动态就是两个线程同属于QQ这个进程。

说完了进程和线程,我们就说一下代码的实现,上文已经提到我们实现的并行搜索要干的事是查找一个元素在数组中出现的次数,如果我们从头到尾遍历数组那么查找的效率就很低,那么我们要是将数组分为两部分甚至四部分,也就是创建两个或四个线程同时查找那么时间消耗就很低因为线程是同时执行的,所以该算法的实现就变得很简单只需要创建好线程,在这我们就创建两个线程并且这两个线程同时执行一个相同的函数进行查找。

代码:

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

using namespace std;

#define DATE_SIZE 1024*1024

typedef struct dateSearch {
	int* date;
	int start;
	int end;
	int count;
}search;

/*查找数据函数*/
DWORD WINAPI parallelSearch(void* section) {
	int number = 10;
	for (int i = ((search*)section)->start;i < ((search*)section)->end;i++) {
		if (number == ((search*)section)->date[i]) {
			((search*)section)->count++;
		}
	}
	return ((search*)section)->count;
}

void initStructMember(search& s, int start, int end, int* date) {
	s.count = 0;
	s.start = start;
	s.end = end;
	s.date = date;
}

int main(void) {
	int* date = new int[DATE_SIZE];
	for (int i = 0;i < DATE_SIZE;i++) {
		date[i] = i;
	}

	int middle = DATE_SIZE / 2;
	search s1, s2;

	initStructMember(s1, 0, middle, date);
	initStructMember(s2, middle + 1, DATE_SIZE, date);

	DWORD threadId1;//线程 1 的身份证
	HANDLE Hthread1 = 0;//获取线程 1 句柄从而对线程进行操作

	DWORD threadId2;//线程 2 的身份证
	HANDLE Hthread2 = 0;//获取线程 2 句柄从而对线程进行操作

	Hthread1 = CreateThread(NULL, 0, parallelSearch, &s1, 0, &threadId1);//创建线程 1
	Hthread2 = CreateThread(NULL, 0, parallelSearch, &s2, 0, &threadId2);//创建线程 2

	WaitForSingleObject(Hthread1, INFINITE);//进程运行到该条语句 等待线程 1 结束 等待的时间为无限长
	WaitForSingleObject(Hthread2, INFINITE);//进程运行到该条语句 等待线程 2 结束 等待的时间为无限长

	cout << s1.count << "   " << s2.count << endl;

	system("pause");
	return 0;
}

创建线程的步骤已经给出,并且已注释如果有什么错误请批评指正。

2:二分查找的思想和分治法的思想类似,现在就给大家分享一下二分查找的思路二分查找可以用递归的形式实现也可以用循环的形式实现在这我们就用循环,什么是二分查找?顾名思义二分查找就是将数组分为开进行查找,为了让思路更加清晰我们就用一个具体实例进行讲解,int int_array[] = { 1,2,3,4,5,6,7,8 }假如我们查找数字 1 在数组中的位置,我们先将数组分为两半并且找到数组中间位置middle对应的数int_array[middle]让该数与要查找的数进行比较,这里middle=4,int_array[middle]=5,因为1<5所以我们将位置锁定在前半个数组也就是int int_array[] = { 1,2,3,4}再进行上述操作也就是middle=2,int_array[middle]=3,1<3 所以现在数组为int int_array[] = { 1,2},1<2 所以现在数组为middle=0,int int_array[] = { 1},int_array[middle]=1,查找到位置为0,并且将该位置返回,现在我们已经将思路讲的很清楚了如果查找的数大于中间位置的数那么就定位到数组的右半边否则定位到数组的左半边,直到数组中间位置的数和要查找的数相同才能返回位置,否则说明数组中没有该数,算法实现的前提是数组是有序的!!!

#include<iostream>
#include<stdlib.h>

using namespace std;

/*查找整数数组中的的元素位置*/
int int_lookUp(const void* number1, const void* number2) {
	const int* p = (int*)number1;
	const int* p1 = (int*)number2;
	return *p - *p1;
}

/*查找字符数组中元素的位置*/
int char_lookUp(const void* str1, const void* str2) {
	const char* p = (char*)str1;
	const char* p1 = (char*)str2;
	return *p - *p1;
}

/*实现二分查找*/
int dichotomyLookUp(void* array, int len, int elemSize, void* number,
	int (*fp)(const void* number1, const void* number2)) {
	int middle = (len-1) / 2;
	int right = len-1, left = 0;
	while (left <= right) {
		/*确定 number 所在的区间*/
		int ret = fp(number, (char*)array + elemSize * middle);

		/*查找到该值时返回*/
		if (ret == 0)return middle;

		/*查找的值小于中间值时*/
		if (ret < 0) {//{ 'a','b','c','d','e','f'};
			right = middle - 1;
			middle = (right + left) / 2;
		}

		/*查找的值大于中间值时*/
		if (ret > 0) {
			left = middle + 1;
			middle = (right + left) / 2;
		}
	}
	/*没有查找到该值时*/
	return -1;
}

int main(void) {
	/*定义整数数组*/
	int int_array[] = { 1,2,3,4,5,6,7,8 };
	int int_len = sizeof(int_array) / sizeof(int_array[0]);

	/*定义字符串数组*/
	char char_array[] = { 'a','b','c','d','e','f'};
	int char_len = sizeof(char_array) / sizeof(char_array[0]);

	/*测试字符串数组*/
	char char_test[] = { 'f'};
	int char_test_len = sizeof(char_test) / sizeof(char_test[0]);
	for (int j = 0;j < char_test_len;j++) {
		char_test[j];
		int i = dichotomyLookUp(char_array, char_len, sizeof(char_array[0]),&char_test[j], char_lookUp);
		if (i == -1)cout << "数组中没有该数字!" << endl;
		else {
			cout << "位置为 " << i << endl;
		}
	}
	cout << "----------" << endl;

	/*测试整数数组*/
	int int_test[] = { 1,3,5,7,10, 8 };
	int int_test_len = sizeof(int_test) / sizeof(int_test[0]);
	for (int j = 0;j < int_test_len;j++) {
		int i = dichotomyLookUp(int_array, int_len, sizeof(int_array[0]), &int_test[j],int_lookUp);
		if (i == -1)cout << "数组中没有该数字!" << endl;
		else {
			cout << "位置为 " << i << endl;
		}
	}

	system("pause");
	return 0;
}

为了让我们写的函数更加具有兼容性在这我们可以查找字符数组也可以查找整数数组甚至浮点数数组,我们就使用了函数指针实现多种类型的查找。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值