C++ 数据结构算法 学习笔记(33) -查找算法及企业级应用

news2024/9/20 10:39:46

C++ 数据结构算法 学习笔记(33) -查找算法及企业级应用

数组和索引

日常生活中,我们经常会在电话号码簿中查阅“某人”的电话号码,按姓查询或者按字母排 序查询;在字典中查阅“某个词”的读音和含义等等。在这里,“电话号码簿”和“字典”都可 看作一张查找表,而按“姓”或者“字母”查询则是按索引查询!

在这里插入图片描述

索引把线性表分成若干块,每一块中的元素存储顺序是任意的,但是块与块间必须按关键字 大小按顺序排列。即前一块中的最大关键字值小于后一块中的最小关键字值。 分块以后,为了快速定义块,还需要建立一个索引表,索引表中的一项对应于线性表中的一 块,索引项由键域和链域组成。键域存放相应关键字的键值,链域存放指向本块第一个节点和最 后一个节点的指针,索引表按关键字由小到大的顺序排列!

数组是特殊的块索引(一个块一个元素):

在这里插入图片描述

哈希表是非常经典的块索引!

在这里插入图片描述

分块查找的算法分两步进行,首先确定所查找的节点属于哪一块,即在索引表中查找其所在的块, 然后在块内查找待查询的数据。由于索引表是递增有序的,可采用二分查找,而块内元素是无序 的,只能采用顺序查找。(块内元素较少,则不会对执行速度有太大的影响

二分查找

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

#include <iostream>
#include <string>

using namespace std;

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 middle = 0;

	left = 0;
	right = len - 1;

	while (left <= right)
	{
		int ret = 0;
		middle = (left + right) / 2;
		ret = compare(static_cast<char *>(sorted)+(elemSize*middle), search);
		if (ret ==0)
		{
			return middle;
		}
		else if (ret >0)
		{
			right = middle - 1;
		}
		else
		{
			left = middle + 1;

		}
	}
	return -1;
}

int main()
{ 
	int arr[] = { 1,3,7,9,11 };
	int search[] = {0,1,7,2,11,12};
	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);
		cout << "The result is: " << index << endl;
	}

	char arr1[] = { 'a','c','d','f','j' };
	char search1[] = {'0','a','e','j','z'};
	cout << endl;

	cout << "Char searching..." << endl;
	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);
		cout << "The result is: " << index << endl;
	}
	system("pause");
	return 0;
}

穷举搜索

有20枚硬币,可能包括4种类型:1元、5角、1角和5分。

已知20枚硬币的总价值为10元,求各种硬币的数量。 例如:4、11、5、0就是一种方案。

而8、2、10、0是另一个可能的方案,显然方案并不是 唯一的,请编写程序求出类似这样的不同的方案一共有多少种?

(1)编程思路。 直接对四种类型的硬币的个数进行穷举。其中,1元最多10枚、5角最多20枚、1角最多 20枚、5分最多20枚。

如果以元为单位,则5角、1角、5分会化成浮点型数据,容易计算出错。可以将1 元、5角、1角、5分变成100分、50分、10分和5分,从而全部采用整型数据处理。

#include <iostream>
#include <string>

using namespace std;

int main()
{
	int a100 = 0; //one dollar coin
	int a50 = 0;
	int a10 = 0;
	int a5 = 0;
	int cnt = 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)
					{
						cout << a100 << "," << a50 << "," << a10 << "," << a5 << "," << endl;
						cnt++;
					}
				}
			}
		}

	}
	cout << "The total method to have the $10 dollar with 20 coin is: " << cnt << endl;


	system("pause");
	return 0;
}

穷举法(枚举法)的基本思想是:列举出所有可能的情况,逐个判断有哪些是符合问题所要求 的条件,从而得到问题的全部解答。 它利用计算机运算速度快、精确度高的特点,对要解决问题的所有可能情况,一个不漏地进行检 查,从中找出符合要求的答案。

用穷举算法解决问题,通常可以从两个方面进行分析:

(1)问题所涉及的情况:问题所涉及的情况有哪些,情况的种数必须可以确定。把它描述 出来。应用穷举时对问题所涉及的有限种情形必须一一列举,既不能重复,也不能遗漏。重复列 举直接引发增解,影响解的准确性;而列举的遗漏可能导致问题解的遗漏。

(2)答案需要满足的条件:分析出来的这些情况,需要满足什么条件,才成为问题的答案。 把这些条件描述出来。

并行搜索

并发的基本概念

所谓并发是在同一实体上的多个事件同时发生。并发编程是指在在同一台计算机上“同时” 处理多个任务。

在这里插入图片描述

要理解并发编程,我们必须要理解如下一些基本概念: 计算机就像一座工厂,时刻在运行,为人类服务。它的核心是CPU,它承担了所有的计算任 务,就像工厂的一个现场指挥官。

在这里插入图片描述

进程就像工厂里的车间,承担“工厂”里的各项具体的“生产任务”,通常每个进程对应一 个在运行中的执行程序,比如,QQ和微信运行的时候,他们分别是不同的进程。

因为特殊原因,现场指挥官人才短缺,整个工厂只有一个指挥官,一次只能指导一个车间生 产,而所有的车间都必须要有现场指挥官在场才能生产。也就是说,一个车间开工的时候, 其他车间都必须停工。

背后的含义:任一时刻,单个CPU一次只能运行一个进程,此时其他进程处于非运行状态。

在这里插入图片描述

一个车间(进程)可以包括多条生产线,线程就好比车间(进程)里的生产线。所有生产线 (设备和人)都属于同一车间的资源,受车间统一调度和调配,并共享车间所有资源(如空 间或洗手间)。

背后的含义:一个进程可以拥有多个线程,每个线程可以可以独立并行执行,多个线程共 享同一进程的资源,受进程管理。

在这里插入图片描述

理解了以上这些概念后,我们接下来再继续讲解并行搜索的概念: 假设我们要从很大的一个无序的数据集中进行搜索,

假设我们的机器可以一次性容纳这么多 数据。从理论上讲,对于无序数据,如果不考虑排序,已经很难从算法层面优化了。而利用 上面我们提到的并行处理思想,我们可以很轻松地将检索效率提升多倍。具体实现思路如下: 将数据分成N个块,每个块由一个线程来并行搜索。

#include <iostream>
#include <string>
#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;

//int main1()
//{
//	int* data = NULL;
//	int count = 0;
//
//	data = new int[TEST_SIZE];
//
//	for (int i = 0; i < TEST_SIZE; i++)
//	{
//		data[i] = i;
//	}
//
//	time_t start = 0, end = 0;
//	time(&start);
//
//	for (int j = 0; j < 10; j++)
//	{
//		for (int i = 0; i < TEST_SIZE; i++)
//		{
//			if (data[i] == NUMBER)
//			{
//				count++;
//			}
//		}
//	}
//
//	time(&end);
//	cout << "The time used for the search function is: " << end - start << endl;
//	system("pause");
//	return 0;
//}

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

	cout << "The new thread is executing..." << endl;
	time(&start);
	for (int j = 0; j < 10; j++)
	{
		for (size_t i = s->start; i < s->end; i++)
		{
			if (s->data[i] == NUMBER)
			{
				s->count++;
			}
		}
	}
	time(&end);
	cout << "The required time to searching the data is: " << end - start << endl;
	return 0;
}

int main()
{
	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; //Thread 1 identity
	HANDLE hThread1; //Thread 1 handle

	DWORD threadID2; //Thread 2 identity
	HANDLE hThread2; //Thread 2 handle

	cout << "Creating the threads..." << endl;

	hThread1 = CreateThread(NULL, 0, ThreadProc, &s1, 0, &threadID1); //Creating first thread
	hThread2 = CreateThread(NULL, 0, ThreadProc, &s2, 0, &threadID2); // Creating second thread

	WaitForSingleObject(hThread1, INFINITE);
	WaitForSingleObject(hThread2, INFINITE);
	cout << "The process is waiting the thread to return..." << endl;
	cout << "The total count for the search value is: " << s1.count + s2.count << endl;
	system("pause");
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1704279.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高弹性架构的微服务设计模式

长期以来&#xff0c;开发人员一直使用单片架构&#xff0c;而且长期以来&#xff0c;这种架构一直有效。不幸的是&#xff0c;这些架构使用的部件较少&#xff0c;但体积较大&#xff0c;这意味着如果一个部件发生故障&#xff0c;它们更有可能整体失效。通常&#xff0c;这些…

《书生·浦语大模型实战营》第1课 学习笔记:书生·浦语大模型全链路开源体系

文章大纲 1. 简介与背景智能聊天机器人与大语言模型目前的开源智能聊天机器人与云上运行模式 2. InternLM2 大模型 简介3. 视频笔记&#xff1a;书生浦语大模型全链路开源体系内容要点从模型到应用典型流程全链路开源体系 4. 论文笔记:InternLM2 Technical Report简介软硬件基础…

HR招聘面试测评,哪些工作岗位需要测评创新能力?

什么是创新能力&#xff1f; 创新能力指在现有的物质基础上&#xff0c;通过某些特定的条件&#xff0c;促成满足未来社会发展的新事物。无论是个人还是国家都需要巨大的创新能力&#xff0c;因为创新是一切发展的根基&#xff0c;离开了创新&#xff0c;所有的发展都是原地踏…

Windows安全基础——Windows WMI详解

Windows安全基础——WMI篇 1. WMI简介 WMI&#xff08;Windows Management Instrumentation, Windows管理规范&#xff09;是Windows 2000/XP管理系统的核心&#xff0c;属于管理数据和操作的基础模块。设计WMI的初衷是达到一种通用性&#xff0c;通过WMI操作系统、应用程序等…

设计模式16——策略模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 策略模式&#xff08;Strategy…

计算机的存储体系

计算机的存储分为内存和硬盘两大类。其中内存属于非持久化的存储设备&#xff0c;用于临时存储数据&#xff0c;设备掉电后数据会丢失&#xff1b;硬盘属于持久化的存储设备&#xff0c;设备掉电后数据不会丢失。 实际上在计算机领域存储的种类是非常多的&#xff0c;业界有时…

linux网卡MAC地址

1、ifconfig命令查看网卡MAC地址 1.1 通过HWaddr或ether字段过滤mac地址 ifconfig | grep HWaddr ifconfig | grep ether [rootlocalhost ~]# /sbin/ifconfig | grep ether 注&#xff1a;有些Linux发行版本的MAC地址字段为HWaddr&#xff0c;有些Linux发行版本的MAC地址字段…

SkyWalking 介绍及部署

1、SkyWalking简介2、SkyWalking的搭建 2.1 部署Elasticsearch2.2 部署SkyWalking-Server2.3 部署SkyWalking-UI3、应用接入 3.1 jar包部署方式3.2 dockerfile方式3.3 DockerFile示例4、SkyWalking UI 界面说明 4.1 仪表盘 4.1.1 APM &#xff08;1&#xff09;全局维度&#x…

clickhouse——ck目录介绍

一、ck目录 1、/etc/clickhouse-server: 服务端的配置文件目录&#xff0c;包括全局配置config.xml和用户配置users.xml等。 2、/var/lib/clickhouse 默认的数据存储目录&#xff08;通常会修改默认路径配置&#xff0c;将数据保存到大容量磁盘挂载的路径&#xff09; 3、/var…

电脑不能远程桌面连接不上,电脑无法建立远程桌面连接如何解决?

电脑无法建立远程桌面连接的问题&#xff0c;通常涉及到多个层面的因素&#xff0c;包括但不限于网络设置、系统配置、防火墙设置以及服务状态等。以下是一些专业性的解决方案&#xff0c;以帮助您解决这一问题。 首先&#xff0c;我们需要检查网络连接。远程桌面连接需要稳定的…

【数据库】通过一个实例来认识数据流图DFD

导读&#xff1a;通过一个实例&#xff08;数据中台&#xff09;说明数据流图DFD的作用、介绍了常见的数据流图元素及其标准符号以及如何画数据流图。数据流图主要被分析师、系统设计师、流程优化专家、系统管理员以及与系统开发和维护相关的人员查看和使用。对于刚考完2024年5…

怎样在网上赚点零花钱?推荐十个正规的赚钱兼职平台

今天要和大家探讨一个激动人心的话题——网络赚钱。在这个互联网日新月异的时代&#xff0c;网络赚钱已经变成了触手可及的现实。如果你正打算在网上赚取一些额外收入&#xff0c;那么这篇文章绝对值得一读&#xff01; 在这个信息泛滥的时代&#xff0c;网络赚钱的机遇随处可…

redis数据操作相关命令

1.list操作 1.1 rpush rpush&#xff1a;新的元素添加到list最右边 #从右边依次往List添加1,2,3 RPUSH name 1 RPUSH name 2 RPUSH name 3#查看列表&#xff1a;返回 1,2,3 LRANGE name 0 -1结果如下&#xff1a; 1.2 lpush lpush&#xff1a;新加的元素在list最左边 #从…

U8G2移植到STM32,SSD13XXXOLED(硬件SPI DMA通讯)

文章目录 一、前言1.1 U8g2的特点1.2 U8G2的优势1.3 U8G2的下载地址1.4 U8g2支持的显示控制器 二、STM32Cubexm SPI DMA配置2.1 SPI设置为半双工模式2.2 SPI DMA设置2.3 oled其他引脚配置 三、移植U8G2框架3.1 精简U8G2库文件3.2 去掉csrc文件夹中无用的驱动文件3.3 文件移动到…

【Java reentrantlock源码解读】

今天学习一下Java中lock的实现方式aqs 直接上图这是lock方法的实现类、分为公平锁和非公平锁两种。 先看非公平的实现方法、很暴力有木有&#xff0c;上来直接CAS&#xff08;抢占锁的方法&#xff0c;是一个原子操作&#xff0c;没有学过的同学自行百度哦&#xff09;&#…

香橙派 Kunpeng Pro使用教程:从零开始打造个人私密博客

一、引言 在这个日益互联的世界中&#xff0c;单板计算机已经成为创新和个性化解决方案的重要载体。而在单板计算机领域&#xff0c;香橙派 Kunpeng Pro凭借其强大的性能和灵活的应用潜力&#xff0c;正逐渐吸引着全球开发者和技术爱好者的目光。 作为一款集成了华为的鲲鹏处…

蓝牙模块、WiFi模块等无线通信模块使用规范

在当今的科技时代&#xff0c;无线通信模块已经广泛应用于各类电子设备中。特别是蓝牙模块、WiFi模块等无线模块&#xff0c;它们为设备间的通信提供了便利&#xff0c;使得我们的生活更加便捷和高效。然而&#xff0c;为了确保这些无线模块正常工作并避免可能的安全隐患&#…

I.MX6ULL的蜂鸣器实验-GPIO输出实验

系列文章目录 I.MX6ULL的蜂鸣器实验 I.MX6ULL的蜂鸣器实验 系列文章目录一、前言二、有源蜂鸣器简介三、硬件原理分析四、程序编写4.1程序编写前提工作4.2程序编写 五、编译下载验证5.1编写 Makefile 和链接脚本5.2编译下载 一、前言 在 I.MX6U-ALPHA 开发板上有一个有源蜂鸣器…

MYSQL框架结构

MYSQL框架结构 通过解析器和预处理生成解析树&#xff0c;预处理判断是否合法&#xff0c;如果合法则调用优化器去进行优化。

PYQT5点击Button执行多次问题解决方案(亲测)

PYQT5点击Button却执行多次问题 使用pyqt5时遇到问题&#xff0c;UI上按钮点击一次&#xff0c;对应的槽函数却执行了3遍 首先&#xff0c;确认函数名无冲突&#xff0c;UI button名无命名冲突&#xff0c;下图是简单的示例程序&#xff1a; 运行后&#xff0c;点击按钮&#…