數據結構基礎:哈希表、排序和查找算法

目錄

一、哈希表

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(n2)穩定相鄰元素比較,大元素后移,重復 n-1 次
選擇排序O(n2)不穩定每次從剩余元素中找最小值,與當前位置交換
插入排序O(n2)穩定將元素插入到已排序序列的合適位置,類似整理撲克牌
希爾排序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…