日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用qsort对不连续的内存数据排序_常见的内排序和外排序算法

發布時間:2024/9/3 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用qsort对不连续的内存数据排序_常见的内排序和外排序算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

常見的內排序算法

所謂的內排序是指所有的數據已經讀入內存,在內存中進行排序的算法。排序過程中不需要對磁盤進行讀寫。同時,內排序也一般假定所有用到的輔助空間也可以直接存在于內存中。與之對應地,另一類排序稱作外排序,即內存中無法保存全部數據,需要進行磁盤訪問,每次讀入部分數據到內存進行排序。我們在9.1.2“常見的外排序算法”中討論該類問題。

1.合并排序

合并排序(Merge Sort)是一種典型的排序算法,應用“分而治之(divide and conquer)”的算法思路,將線性數據結構(如array、vector或list)分為兩個部分,對兩部分分別進行排序,排序完成后,再將各自排序好的兩個部分合并還原成一個有序結構。由于合并排序不依賴于隨機讀寫,因此具有很強的普適性,適用于鏈表等數據結構。算法的時間復雜度為O(nlogn),如果是處理數組需要額外O(n)空間,處理鏈表只需要O(1)空間。算法實現如下:

void merge_sort( int array[], int helper[], int left, int right){  if( left >= right )    return;  // divide and conquer: array will be divided into left part and right part  // both parts will be sorted by the calling merge_sort  int mid = right - (right - left) / 2;  merge_sort( array, helper, left, mid );  merge_sort( array, helper, mid + 1, right);  // now we merge two parts into one  int helperLeft = left;  int helperRight = mid + 1;  int curr = left;  for(int i = left; i <= right; i++)    helper[i] = array[i];  while( helperLeft <= mid && helperRight <= right ){    if( helper[helperLeft] <= helper[helperRight] )      array[curr++] = helper[helperLeft++];    else      array[curr++] = helper[helperRight++];  }  // left part has some large elements remaining. Put them into the right side  while( helperLeft <= mid )    array[curr++] = helper[helperLeft++];}

當遞歸調用merge_sort返回時,array的左右兩部分已經分別由子函數排序完成,我們利用helper數組暫存array中的數值,再利用兩個while循環完成合并。helper數組的左右半邊就是兩個排序完的隊列,第一個while循環相當于比較隊列頭,將較小的元素取出放入array,最后使得array的左半邊由小到大排序完成。第二個while循環負責掃尾,把helper左半邊剩余元素復制入array中。注意,此時我們不需要對helper右半邊做類似操作,因為即使右半邊有剩余元素,它們也已經處于array中恰當的位置。

關于合并排序更多理論方面的討論,請見9.3“工具箱”。

2.快速排序

快速排序(Quick Sort)是最為常用的排序算法,C++自帶的排序算法的實現就是快速排序。該算法以其高效性,簡潔性,被評為20世紀十大算法之一(雖然合并排序與堆排序的時間復雜度量級相同,但一般還是比快速排序慢常數倍)。快速排序的算法核心與合并排序類似,也采用“分而治之”的想法:隨機選定一個元素作為軸值,利用該軸值將數組分為左右兩部分,左邊元素都比軸值小,右邊元素都比軸值大,但它們不是完全排序的。在此基礎上,分別對左右兩部分遞歸調用快速排序,使得左右部分完全排序。算法的平均時間復雜度是O(nlogn),在最壞情況下為O(n^2),額外空間復雜度為O(logn)。算法實現如下:

int partition( int array[], int left, int right ) {  int pivot = array[right];  while( left != right ){    while( array[left] < pivot && left < right)      left++;    if (left < right) {      swap( array[left], array[right--]);    }    while( array[right] > pivot && left < right)      right--;    if( left < right )      swap( array[left++], array[right]);  }  //array[left] = pivot;  return left;}void qSort( int array[], int left, int right ){  if( left >=right )    return;  int index = partition( array, left, right);  qSort(array, left, index - 1);  qSort(array, index + 1, right);}

partition函數先選定數組right下標所指的元素作為軸值,用pivot變量存儲該元素值。然后,右移left,即從左向右掃描數組,直到發現某個元素大于軸值或者掃描完成。如果某個元素大于軸值,則將該元素與軸值交換。該操作特性在于:保證交換后軸值左側的元素都比軸值小。再次,左移right,即從右向左掃描數組,直到發現某個元素小于軸值或者掃描完成。如果某個元素小于軸值,則將該元素與軸值交換。該操作特性在于:保證交換后軸值右側的元素都比軸值大。重復上述過程直到left和right相遇,最終相遇的位置即為軸值所在位置。由于上述操作的特性,最終軸值左側的元素都比軸值小,軸值右側的元素都比軸值大。

關于快速排序的更多理論討論請見9.3“工具箱”。C++標準模版庫提供函數sort,實現快速排序的功能:sort( iterator first, iterator last, Compare comp ); // can also be pointers here。

3.堆排序

堆排序(Heap Sort)利用了我們在第5章中提到的堆作為邏輯存儲結構,將輸入array變成一個最大值堆。然后,我們反復進行堆的彈出操作。回顧之前所述的彈出過程:將堆頂元素與堆末元素交換,堆的大小減一,向下移動新的堆頂以維護堆的性質。事實上,該操作等價于每次將剩余的最大元素移動到數組的最右邊,重復這樣的操作最終就能獲得由小到大排序的數組。初次建堆的時間復雜度為O(n),刪除堆頂元素并維護堆的性質需要O(logn),這樣的操作一共進行n次,故最終時間復雜度為O(nlogn)。我們不需要利用額外空間,故空間復雜度O(1)。具體實現如下:

void heapSort(int array[], int size) {   Heapify(array, size);  for (int i = 0; i < size - 1; i++)           popHeap(array);}

Heapify和popHeap的實現參考本書第5章。

4.桶排序和基數排序

桶排序(Bucket Sort)和基數排序(Radix Sort)不需要進行數據之間的兩兩比較,但是需要事先知道數組的一些具體情況。特別地,桶排序適用于知道待排序數組大小范圍的情況。其特性在于將數據根據其大小,放入合適的“桶(容器)”中,再依次從桶中取出,形成有序序列。具體實現如下:

void BucketSort(int array[], int n, int max){  // array of length n,all records in the range of [0,max)  int tempArray[n];  int i;  for (i = 0; i < n; i++)    tempArray[i] = array[i];  int count[max];  // buckets  memset(count, 0, max * sizeof(int));  for (i = 0; i < n; i++)  // put elements into the buckets    count[array[i]]++;  for (i = 1; i < max; i++)    count[i] = count[i-1] + count [i]; // count[i] saves the starting index (in array) of value i+1  // for value tempArray[i], the last index should be count[tempArray[i]]-1  for (i = n-1; i >= 0; i--)    array[--count[tempArray[i]]] = tempArray[i];}

該實現總的時間代價為O(max+n),適用于max相對n較小的情況。空間復雜度也為O(max+n),用以記錄原始數組和桶計數。

桶排序只適合max很小的情況,如果數據范圍很大,可以將一個記錄的值即排序碼拆分為多個部分來進行比較,即使用基數排序。基數排序相當于將數據看作一個個有限進制數,按照由高位到低位(適用于字典序),或者由低位到高位(適用于數值序)進行排序。排序具體過程如下:對于每一位,利用桶排序進行分類,在維持相對順序的前提下進行下一步排序,直到遍歷所有位。該算法復雜度為O(k*n),k為位數(或者字符串長度)。直觀上,基數排序進行了k次桶排序。具體實現如下:

void RadixSort(int Array[], int n, int digits, int radix){  // n is the length of the array  // digits is the number of digits  int *TempArray = new int[n];  int *count = new int[radix]; // radix buckets  int i, j, k;  int Radix = 1; // radix modulo, used to get the ith digit of Array[j]  // for ith digit  for (i = 1; i <= digits; i++) {    for (j = 0; j < radix; j++)      count[j] = 0;      // initialize counter    for (j = 0; j < n; j++)   {      // put elements into buckets      k = (Array[j] / Radix) % radix; // get a digit      count[k]++;    }    for (j = 1; j < radix; j++) {      // count elements in the buckets      count[j] = count[j-1] + count[j];    }    // bucket sort    for (j = n-1; j >= 0; j--) {      k = (Array[j] / Radix ) % radix;      count[k]--;      TempArray[count[k]] = Array[j];    }    for (j = 0; j < n; j++) {      // copy data back to array      Array[j] = TempArray[j];    }    Radix *= radix;   // get the next digit  }}

與其他排序方式相比,桶排序和基數排序不需要交換或比較,它更像是通過逐級的分類來把元素排序好。

常見的外排序算法

外排序算法的核心思路在于把文件分塊讀到內存,在內存中對每塊文件依次進行排序,最后合并排序后的各塊數據,依次按順序寫回文件。外排序需要進行多次磁盤讀寫,因此執行效率往往低于內排序,時間主要花費于磁盤讀寫上。我們給出外排序的算法步驟如下:

假設文件需要分成k塊讀入,需要從小到大進行排序。

(1)依次讀入每個文件塊,在內存中對當前文件塊進行排序(應用恰當的內排序算法)。此時,每塊文件相當于一個由小到大排列的有序隊列。

(2)在內存中建立一個最小值堆,讀入每塊文件的隊列頭。

(3)彈出堆頂元素,如果元素來自第i塊,則從第i塊文件中補充一個元素到最小值堆。彈出的元素暫存至臨時數組。

(4)當臨時數組存滿時,將數組寫至磁盤,并清空數組內容。

(5)重復過程(3)、(4),直至所有文件塊讀取完畢。

本文節選自《程序員面試白皮書》

本書是程序員和IT從業人員的面試求職指南。本書遵從大多數面試參考圖書的組織方式,結合實例,按照常見的數據結構、算法以及計算機基礎知識進行章節劃分。每一章的“知識要點”部分介紹章節涉及的相關知識點,回顧重要的基礎知識點;“模式識別”部分給出一些例題,幫助大家總結解決相關問題的常見方法,并且通過分析問題中的關鍵信息,教授讀者如何從題目中分析題型和解題方法。程序員面試是對于面試者計算機知識的全面檢測,因此,本書設有專門的章節覆蓋了網絡、操作系統、編譯器、算法和數據結構等等各個領域的知識。

本書作者來自硅谷一線的IT公司,書中包含了作者親身的經驗和體驗,書中收集的題目部分來自互聯網上分享的面試經驗、在線編程網站leetcode,以及一些著名的面試參考資料。本書適合想要從事正規的程序員、架構師以及相關IT公司的專業人士和學生參考,尤其適合那些以一線IT外企或互聯網公司為求職目標的讀者閱讀。

總結

以上是生活随笔為你收集整理的使用qsort对不连续的内存数据排序_常见的内排序和外排序算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 精品欧美一区二区三区在线观看 | 欧美日韩三级在线观看 | www.五月婷婷 | 国产视频一二三四区 | 日韩亚洲欧美在线观看 | 成人av中文解说水果派 | 日韩成人在线免费观看 | 高清国产一区二区 | 男男play呻吟动漫网站 | 日日撸夜夜撸 | 亚洲一线在线观看 | 在线免费看mv的网站入口 | 亚洲精品国产精品国自产观看 | 精品欧美一区二区在线观看 | 欧美色图19p | √天堂资源地址在线官网 | 日批av | 国产成人精品网 | 亚洲精品在线播放视频 | 99精品综合 | 午夜鲁鲁 | 国产精品一线二线 | 欧美日韩少妇 | 亚洲乱码国产乱码精品精软件 | 精品无码久久久久成人漫画 | 亚洲超碰在线观看 | 综合网视频 | 一炮成瘾1v1高h| 日本一区二区三区欧美 | 国产欧美一区二区三区视频 | 青青草视频播放 | 久久两性视频 | 成人免费a级片 | 亚洲欧美激情视频 | 国产精品无码在线播放 | 国产精品久久久久9999爆乳 | 成人午夜激情影院 | 国产精品扒开做爽爽爽的视频 | 99色亚洲| 欧美一级大黄 | 综合成人| xxxx久久| 视频在线日韩 | 国产又粗又猛又爽又黄的网站 | 大咪咪dvd | 男人插女人下面视频 | 午夜电影在线播放 | 黄色一级a毛片 | 日本久草视频 | 香蕉视频性 | 青青视频免费 | 三上悠亚在线一区二区 | 91国偷自产一区二区三区女王 | 影音先锋日韩资源 | 麻豆www | 性感美女高潮 | 午夜丰满寂寞少妇精品 | www.国产一区 | 一级片黄色 | 久久国产成人精品国产成人亚洲 | 在线视频www | 久久看看| 尤物最新网址 | 国产女主播在线播放 | 黄色裸体片 | 日韩 欧美 综合 | 在线一级片 | 清纯唯美亚洲色图 | 懂色av蜜臀av粉嫩av分享吧最新章节 | 久久网中文字幕 | 国产全是老熟女太爽了 | 男人天堂999| av在线资源观看 | 日韩精品影视 | 热久久国产精品 | 日韩久久一级片 | 欧美黄色特级片 | 色图色小说 | 国产一区二区三区视频在线观看 | 成人吃奶视频 | 天天干妹子 | 秋霞av鲁丝片一区二区 | 91在线精品一区二区三区 | 无遮挡aaaaa大片免费看 | 久久久久久久久久久久久久av | 国产欧美123 | 欧美与黑人午夜性猛交久久久 | av男人天堂av | 黑人和白人做爰 | 一级黄色电影片 | 日韩一区二区免费在线观看 | 最新毛片网| 国产麻豆精品一区 | 免费人成年激情视频在线观看 | 亚州av网 | 好妞色妞国产在线视频 | 秋霞在线一区 | av影视在线观看 | 亚洲丝袜天堂 |