目录

一、哈希表

1.哈希算法

2.哈希碰撞

3.哈希表

4.哈希表相关操作

哈希表插入

哈希表遍历

元素查找

哈希表销毁

二、排序算法

1. 排序算法对比

2. 排序算法实现

冒泡排序

选择排序

插入排序

希尔排序

快速排序

三、查找算法

1. 查找算法对比

2. 查找算法实现

顺序查找

折半查找(二分查找)

一、哈希表

1.哈希算法

  1. 将数据通过哈希算法映射成一个键值,存取都在同一个位置实现数据的高效存储和查找,将时间复杂度尽可能降低至O(1)
  2. 哈希算法是不固定的,需要选择一个合适的哈希算法,才能映射成一个键值

2.哈希碰撞

多个数据通过哈希算法得到的键值相同,称为产生哈希碰撞

3.哈希表

  • 构建一个哈希表,存放0~100之间的数据
  • 哈希算法的选择:

将0~100之间的数据的个位作为键值 

哈希表通过哈希函数实现高效存取,需解决哈希碰撞

4.哈希表相关操作

哈希表插入
#define INDEX 10  // 假设哈希表大小为10(0-9)
linknode *phashtable[INDEX] = {NULL};  // 哈希表数组/* 哈希表插入函数 */
int insert_hashtable(int tmpdata) {int key = 0;linknode **pptmpnode = NULL;  // 二级指针用于修改链表节点linknode *pnewnode = NULL;// 计算哈希键值(取数据的个位)key = tmpdata % INDEX;// 找到插入位置(保持链表有序)for (pptmpnode = &phashtable[key]; *pptmpnode != NULL && (*pptmpnode)->data < tmpdata; pptmpnode = &(*pptmpnode)->pnext) {// 循环移动指针至合适位置}// 申请新节点pnewnode = malloc(sizeof(linknode));if (NULL == pnewnode) {perror("fail to malloc");return -1;}// 插入新节点pnewnode->data = tmpdata;pnewnode->pnext = *pptmpnode;*pptmpnode = pnewnode;return 0;
}
哈希表遍历
/* 遍历哈希表所有元素 */
int show_hashtable(void) {int i = 0;linknode *ptmpnode = NULL;for (i = 0; i < INDEX; i++) {printf("%d:", i);  // 打印键值ptmpnode = phashtable[i];while (ptmpnode != NULL) {printf("%2d ", ptmpnode->data);  // 打印链表元素ptmpnode = ptmpnode->pnext;}printf("\n");}return 0;
}
元素查找
/* 查找哈希表中的元素 */
linknode *find_hashtable(int tmpdata) {int key = 0;linknode *ptmpnode = NULL;key = tmpdata % INDEX;  // 计算键值ptmpnode = phashtable[key];// 遍历对应链表查找元素while (ptmpnode != NULL && ptmpnode->data <= tmpdata) {if (ptmpnode->data == tmpdata) {return ptmpnode;  // 找到返回节点地址}ptmpnode = ptmpnode->pnext;}return NULL;  // 未找到返回NULL
}
哈希表销毁
/* 销毁哈希表,释放所有节点 */
int destroy_hashtable(void) {int i = 0;linknode *ptmpnode = NULL;linknode *pfreenode = NULL;for (i = 0; i < INDEX; i++) {ptmpnode = phashtable[i];pfreenode = phashtable[i];while (ptmpnode != NULL) {ptmpnode = ptmpnode->pnext;free(pfreenode);  // 释放当前节点pfreenode = ptmpnode;}phashtable[i] = NULL;  // 置空数组元素}return 0;
}

二、排序算法

排序算法中,冒泡、选择、插入排序适用于小规模数据;希尔、快速排序适用于大规模数据,其中快速排序性能最优(平均 O (nlogn))

1. 排序算法对比

算法时间复杂度稳定性核心思想
冒泡排序O(n²)稳定相邻元素比较,大元素后移,重复 n-1 次
选择排序O(n²)不稳定每次从剩余元素中找最小值,与当前位置交换
插入排序O(n²)稳定将元素插入到已排序序列的合适位置,类似整理扑克牌
希尔排序O(n^1.3)不稳定按步长分割数组为子序列,分别插入排序,逐步减小步长至 1
快速排序O(nlogn)不稳定选基准值,将数组分为小于和大于基准的两部分,递归排序两部分

2. 排序算法实现

冒泡排序

核心思想是通过相邻元素的比较和交换,使较大的元素逐步 “浮” 到数组的末尾。具体来说,相邻的两个元素比较,大的向后走,小的向前走,循环找出数组中 len-1 个较大的值,最终实现整个数组的有序排列

/* 冒泡排序:相邻元素比较交换,大元素后移 */
int bubble_sort(int *parray, int len) {int i = 0;int j = 0;int tmp = 0;for (j = 0; j < len - 1; j++) {  // 控制轮次for (i = 0; i < len - 1 - j; i++) {  // 每轮比较次数递减if (parray[i] > parray[i + 1]) {// 交换元素tmp = parray[i];parray[i] = parray[i + 1];parray[i + 1] = tmp;}}}return 0;
}
选择排序

核心思想是从前到后在未排序元素中寻找最小值,然后将找到的最小值与未排序部分的前面元素进行交换。通过找到 len-1 个最小值,最后剩下的一个元素自然就是最大值,从而完成排序

/* 选择排序:找最小值并交换到当前位置 */
int select_sort(int *parray, int len) {int i = 0;int j = 0;int tmp = 0;int min = 0;  // 最小值索引for (j = 0; j < len - 1; j++) {min = j;  // 假设当前位置为最小值for (i = j + 1; i < len; i++) {if (parray[i] < parray[min]) {min = i;  // 更新最小值索引}}// 交换最小值到当前位置if (min != j) {tmp = parray[min];parray[min] = parray[j];parray[j] = tmp;}}return 0;
}
插入排序

核心思想是将数组中的每个元素逐个插入到已排序的数列中。首先取出要插入的元素,然后依次和前面的元素比较,比该元素大的元素向后移动,直到遇到前一个元素比要插入的元素小,或者到达有序数列的开头时停止,最后将该元素插入到合适位置

/* 插入排序:将元素插入已排序序列的合适位置 */
int insert_sort(int *parray, int len) {int tmp = 0;  // 待插入元素int i = 0;int j = 0;for (j = 1; j < len; j++) {tmp = parray[j];  // 取出待插入元素// 找到插入位置for (i = j; i > 0 && tmp < parray[i - 1]; i--) {parray[i] = parray[i - 1];  // 元素后移}parray[i] = tmp;  // 插入元素}return 0;
}
希尔排序

核心思想是通过选择不同的步长,将数组拆分成若干个小的子数组,对每个子数组进行插入排序。当若干个子数组成为有序数列后,数组中的数据会大致有序,最后再对整体进行一次插入排序,以完成整个数组的排序

步长为5

步长为2

步长为1

/* 希尔排序:按步长分割子序列,逐步缩小步长 */
int shell_sort(int *parray, int len) {int step = 0;  // 步长int j = 0;int i = 0;int tmp = 0;// 步长初始为len/2,每次减半至0for (step = len / 2; step > 0; step /= 2) {// 对每个子序列进行插入排序for (j = step; j < len; j++) {tmp = parray[j];for (i = j; i >= step && tmp < parray[i - step]; i -= step) {parray[i] = parray[i - step];  // 元素后移}parray[i] = tmp;  // 插入元素}}return 0;
}
快速排序

核心思想是选择数组左边的元素作为键值,从数组后面找一个比键值小的元素放到前面,再从前面找一个比键值大的元素放到后面,最后将键值放到中间位置。如果左右两边还有元素,则递归调用快速排序对两边元素进行排序

/* 快速排序:分治思想,以基准值分割数组 */
int quick_sort(int *parray, int low, int high) {int key = 0;  // 基准值int i = low;  // 左指针int j = high; // 右指针if (low >= high) {return 0;  // 递归终止条件}key = parray[low];  // 选最左元素为基准值while (i < j) {// 从右向左找小于基准值的元素while (i < j && parray[j] >= key) {j--;}if (i < j) {parray[i] = parray[j];  // 移至左指针位置}// 从左向右找大于基准值的元素while (i < j && parray[i] <= key) {i++;}if (i < j) {parray[j] = parray[i];  // 移至右指针位置}}parray[i] = key;  // 基准值归位// 递归排序左半部分if (i - 1 > low) {quick_sort(parray, low, i - 1);}// 递归排序右半部分if (i + 1 < high) {quick_sort(parray, i + 1, high);}return 0;
}

三、查找算法

查找算法中,折半查找效率远高于顺序查找,但依赖有序数据

1. 查找算法对比

算法时间复杂度适用场景核心思想
顺序查找O(n)无序或小规模数据从前往后依次遍历,逐个比较

折半查找

(二分查找)

O(logn)有序数组每次取中间元素比较,缩小查找范围至左半或右半部分

2. 查找算法实现

顺序查找

从数组的起始位置开始,逐个将元素与要查找的目标值进行比较,若找到与目标值相等的元素,则查找成功;若遍历完整个数组都没有找到,则查找失败

/* 顺序查找:遍历数组逐个比较 */
int seq_search(int *parray, int len, int target) {int i = 0;for (i = 0; i < len; i++) {if (parray[i] == target) {return i;  // 找到返回索引}}return -1;  // 未找到返回-1
}
折半查找(二分查找)

针对有序数组,先计算中间位置,将中间位置的元素与目标值比较。如果目标值等于中间元素,则查找成功;如果目标值大于中间元素,则在数组的右半部分继续查找;如果目标值小于中间元素,则在数组的左半部分继续查找,重复此过程直至找到目标值或确定查找范围为空

/* 折半查找:仅适用于有序数组 */
int binary_search(int *parray, int low, int high, int target) {int mid = 0;if (low > high) {return -1;  // 查找失败}mid = (low + high) / 2;  // 计算中间索引if (parray[mid] == target) {return mid;  // 找到返回索引} else if (target > parray[mid]) {// 目标在右半部分,递归查找return binary_search(parray, mid + 1, high, target);} else {// 目标在左半部分,递归查找return binary_search(parray, low, mid - 1, target);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux内核参数调优:为K8s节点优化网络性能

在高并发微服务环境中&#xff0c;网络性能往往成为K8s集群的瓶颈。本文将深入探讨如何通过精细化的Linux内核参数调优&#xff0c;让你的K8s节点网络性能提升30%以上。引言&#xff1a;为什么网络调优如此重要&#xff1f;作为一名在生产环境中维护过数千节点K8s集群的运维工程…

全家桶” 战略如何重塑智能服务标准?无忧秘书 AI + 智脑 + 数字人协同模式的底层架构解析

在数字化浪潮的推动下&#xff0c;企业对智能化服务的需求日益增长。然而&#xff0c;单一的技术或产品往往难以满足复杂场景下的多样化需求。近年来&#xff0c;“全家桶”战略成为科技行业的一大趋势&#xff0c;通过整合多维度技术与服务&#xff0c;为企业提供全方位的支持…

前端后端之争?JavaScript和Java的特性与应用场景解析

一、名字相似&#xff0c;本质迥异 1.1 历史渊源与命名背景 在编程世界中&#xff0c;很少有两种语言像JavaScript和Java这样&#xff0c;仅仅因为名字的相似性就引发了无数初学者的困惑。然而&#xff0c;这种相似性纯属巧合——或者说是一种营销策略的产物。 JavaScript诞…

【文献分享】Machine learning models提供数据和代码

数据输入及前期信息&#xff1a;ChronoGauge 需要一个基因表达矩阵&#xff0c;其中包括来自多个时间进程 RNA-测序实验的观测数据&#xff0c;用于训练&#xff0c;并且需要有关每个基因在连续光照&#xff08;LL&#xff09;条件下经过光暗&#xff08;LD&#xff09;周期调整…

PHP MySQL Delete 操作详解

PHP MySQL Delete 操作详解 引言 在Web开发中&#xff0c;数据库是存储和管理数据的重要工具。PHP作为一种流行的服务器端脚本语言&#xff0c;与MySQL数据库结合使用可以高效地处理数据。本文将详细介绍PHP中如何使用DELETE语句删除MySQL数据库中的数据。 什么是DELETE语句&am…

计组-大/小端存放区别

在计算机系统中&#xff0c;大端存放&#xff08;Big-Endian&#xff09;和小端存放&#xff08;Little-Endian&#xff09;是两种不同的多字节数据存储方式&#xff0c;主要区别在于字节在内存中的排列顺序。理解它们对底层编程&#xff08;如网络通信、二进制文件处理、硬件交…

线程同步相关知识

文章目录一、线程同步的核心目标二、线程安全的判定条件三、同步方式一&#xff1a;synchronized 关键字1. 同步代码块2. 同步方法四、锁的释放与不释放场景1. 自动释放锁的场景2. 不会释放锁的场景五、同步方式二&#xff1a;ReentrantLock&#xff08;显式锁&#xff09;1. 核…

Armoury Crate无法通过BIOS卸载

设备&#xff1a;天选4 Armoury Crate窗口反复弹出影响使用体验&#xff0c;但无法通过BIOS关闭该怎么办&#xff1f;本文以天选4为例提供解决方案。 Step1&#xff1a;进入服务支持官网 Armoury Crate-服务支持 下滑点击”查看更多” 下载安装卸载工具 得到Armoury_Crate_Un…

如何将视频转为GIF格式,3大视频转为GIF工具

在社交媒体和即时通讯盛行的当下&#xff0c;GIF 动图以其独特的魅力备受青睐。它能够生动地捕捉视频中的精彩瞬间&#xff0c;凭借体积小巧、无需复杂加载且可循环播放的特性&#xff0c;成为了人们在网络交流中表达情感、分享趣事的得力工具。无论是制作诙谐幽默的表情包&…

开发避坑指南(22):Vue3响应式编程中this绑定机制与解决方案

错误信息 TypeError: Cannot read properties of undefined (reading find) TypeError: r.vnode.el.querySelector is not a function报错背景 vue2项目升级到vue3后&#xff0c;原来的代码报错。 报错代码computed: {/** 计算列的显示与隐藏*/columnVisible() {return functio…

AI学习笔记三十五:实时传输视频

若该文为原创文章&#xff0c;转载请注明原文出处。 目的是实现视频的传输&#xff0c;只是个demo. 程序分为两部分&#xff0c;视频接收端和视频发送端。 一、视频接收端流程分析 主要流程&#xff1a; 初始化配置&#xff1a; 设置UDP端口&#xff08;5001&#xff09;和缓…

【ArcGIS】分区统计中出现Null值且Nodata无法忽略的问题以及shp擦除(erase)的使用——以NDVI去水体为例

需求 已有某地NDVI栅格、行政区shp以及水体shp&#xff0c;计算每个行政区的平均NDVI 问题 1.如果不剔除水体 负值NDVI会把平均值拉低 且水体NDVI并不全为负 需要通过shp剔除&#xff0c;Mask掩膜是提取水体本身而不是剩余部分 2.使用分区统计工具&#xff08;Zonal statis…

Linux中的内核同步源码相关总结

什么是内核同步Linux 内核同步是指内核中用于解决并发执行单元&#xff08;如进程、中断、内核线程等&#xff09;对共享资源&#xff08;如全局数据结构、硬件寄存器、链表等&#xff09;的竞争访问的一系列机制和技术。其核心目标是保证多个并发单元在操作共享资源时的数据一…

WORD接受修订,并修改修订后文字的颜色

在 Word 中&#xff0c;接受修订之后默认会采用正文的默认字体格式&#xff0c;不会保留修订时设置的颜色&#xff0c;比如“插入内容是蓝色字体”的设置会被清除。 如果你想要做到&#xff1a;✅ 接受所有修订后仍然让“原插入的文字”变为蓝色字体保留下来你只能通过一些手动…

行业速览:中国新能源汽车市场格局与关键趋势

在全球汽车产业迈向绿色、低碳、智能化的变革浪潮中&#xff0c;新能源汽车已成为各国争夺的战略高地。中国&#xff0c;作为全球最大的汽车市场和新能源汽车制造国&#xff0c;正以强大的市场规模、完整的产业链体系以及快速提升的技术创新能力&#xff0c;在这场变革中不断加…

【51单片机2个按键控制流水灯转向】2022-10-25

缘由51单片机按键流水灯-嵌入式-CSDN问答 #include "REG52.h" sbit k1P3^0; sbit k2P3^1; void main() {unsigned char l0,xd0,ys10,ys20,z0;P1l;while(1){if(k10&&xd0){z0;while(k10);}if(k20&&xd0){z1;while(k20);}if(ys10)if(ys20){if(z0)if(l0)…

flutter开发(一)flutter命令行工具

安装 Linux下面的flutter安装比较简单&#xff0c;在flutter 中文战 上下载一个最新稳定的版本&#xff0c;解压到系统上就行了。 我下载的是Linux下的3.32.7版。 解压之后&#xff0c;flutter目录里会有bin、dev等目录&#xff0c;把bin目录加到系统的PATH环境变量里&#…

OpenCV 入门实战:从环境配置到图像 / 视频处理

OpenCV 是计算机视觉领域最常用的开源库之一&#xff0c;它提供了丰富的图像和视频处理功能。本文将从环境配置开始&#xff0c;带大家一步步解析基础操作代码&#xff0c;快速入门 OpenCV 的使用。 一、环境配置 在开始之前&#xff0c;我们需要先搭建好 OpenCV 的运行环境。…

2.2.1 饰面板材和陶瓷的特性和应用

1、饰面石材1&#xff09;天然花岗岩2&#xff09;天然大理石3&#xff09;人造石&#xff08;1&#xff09;人造石按主要原材料分包括人造石实体面材、人造石英石和人造石岗石等产品。2、建筑卫生陶瓷建筑卫生陶瓷包括建筑陶瓷和卫生陶瓷两大类。建筑陶瓷包括陶瓷砖、建筑琉璃…

C++的结构体数组

结构体数组的基础知识 结构体数组通过​​组合数据批量管理​​的特性&#xff0c;广泛应用于学生管理、游戏角色属性存储等场景。常见问题 ​​数组越界​​&#xff1a;静态数组长度固定&#xff0c;超过数组长度的访问&#xff0c;会导致未定义行为。​​未初始化成员​​&a…