排序下---(冒泡排序,快速排序,快速排序優化,快速排序非遞歸,歸并排序,計數排序)

排序上

排序上

交換類排序

基本思想:所謂交換,就是根據序列中兩個記錄鍵值的比較結果來對換這兩個記錄在序列中的位置,交換排序的特點是:將鍵值較大的記錄向序列的尾部移動,鍵值較小的記錄向序列的前部移動。

冒泡排序

在這里插入圖片描述

冒泡排序的特性總結:

  1. 冒泡排序是一種非常容易理解的排序
  2. 時間復雜度:O(N^2)
  3. 空間復雜度:O(1)
  4. 穩定性:穩定

代碼實現

void BublleSort(int*array, int size)
{for (int i = 0; i < size - 1; ++i)       //總共冒泡的趟數{//冒泡的方式----->用相鄰元素進行比較for (int j = 0; j < size - i - 1; ++j)		//一次冒泡{if (array[j]>array[j + 1])Swap(&array[j], &array[j + 1]);}}
}

冒泡排序優化

void BublleSort(int*array, int size)
{	for (int i = 0; i < size - 1; ++i)       //總共冒泡的趟數{int IsChange = 0;			//查看這一趟有沒有交換//冒泡的方式----->用相鄰元素進行比較for (int j = 0; j < size - i - 1; ++j)		//一次冒泡{if (array[j]>array[j + 1]){Swap(&array[j], &array[j + 1]);IsChange = 1;}	}if (!IsChange)  //如果沒有交換return;}
}

快速排序

一種二叉樹結構的交換排序方法,其基本思想為:任取待排序元素序列中的某元素作為基準值,按照該排序碼將待排序集合分割成兩子序列,左子序列中所有元素均小于基準值,右子序列中所有元素均大于基準值,然后最左右子序列重復該過程,直到所有元素都排列在相應位置上為止。

快速排序的特性總結:
  1. 快速排序整體的綜合性能和使用場景都是比較好的,所以才敢叫快速排序
  2. 時間復雜度:O(N*logN),最差場景,單支樹O(N2)
  3. 空間復雜度:O(logN)
  4. 穩定性:不穩定
  5. 快排參考鏈接

代碼實現

int Partion(int*array, int left, int right)
{//劃分基準值
}
void QuickSort(int *array, int left, int right)
{if (right - left > 1){int div = Partion(array, left, right);QuickSort(array, left, div);QuickSort(array, div + 1, right);}
}

劃分基準值的方式

  1. hoare版本
int Partion(int*array, int left, int right)
{int key = array[right - 1];int begin = left;int end = right - 1;while (begin<end){//從前往后找比基準值大的元素,找到就停下來,等于也往前走,因為找的是大的while (begin < end&&array[begin] <= key)begin++;//end從后往前找比基準值小的元素,找到就停下來,等于也往前走,找的是小的,不是等于while (begin < end&&array[end] >= key)end--;if (begin < end)Swap(&array[begin], &array[end]);}if (begin != right - 1)Swap(&array[begin], &array[right-1]);return begin;
}
  1. 挖坑法
int Partion2(int*array, int left, int right)
{int key = array[right - 1];int begin = left;int end = right - 1;while (begin<end){while (begin<end&&array[begin] <= key)begin++;if (begin<end){//上一個坑是end,begin是比基準值大的數array[end] = array[begin];end--;}while (begin<end&&array[end] >= key)end--;if (begin<end){//上次坑是end,填坑的是begin,填完坑后,begin成坑,由新end比基準值小的數來填array[begin] = array[end];begin++;}}array[begin] = key;return begin;
}
  1. 前后指針版本
int Partion3(int*array, int left, int right)
{int key = array[right - 1];int cur = left;int pre = cur - 1;while (cur<right){if (array[cur] < key && ++pre != cur)Swap(&array[cur], &array[pre]);cur++;}if (++pre != right - 1)Swap(&array[pre], &array[right - 1]);return pre;
}

快排的優化

  1. 三數取中法選key
  2. 遞歸到小的子區間時,可以考慮使用插入排序
三數取中法
//三數取中法
int GetMiddleIdx(int*array, int left, int right)
{int mid = left + ((right - left) >> 1);//left mid right-1if (array[left] < array[right - 1]){if (array[mid] < array[left])return left;else if (array[mid]>array[right - 1])return right - 1;elsereturn mid;}else{if (array[mid] > array[left])return left;else if (array[mid] < array[right - 1])return right - 1;elsereturn mid;}
}
int Partion(int*array, int left, int right)
{int middle = GetMiddleIdx(array, left, right);if (middle != right - 1)Swap(&array[middle], &array[right - 1]);int key = array[right - 1];int begin = left;int end = right - 1;while (begin<end){//從前往后找比基準值大的元素,找到就停下來,等于也往前走,因為找的是大的while (begin < end&&array[begin] <= key)begin++;//end從后往前找比基準值小的元素,找到就停下來,等于也往前走,找的是小的,不是等于while (begin < end&&array[end] >= key)end--;if (begin < end)Swap(&array[begin], &array[end]);}if (begin != right - 1)Swap(&array[begin], &array[right - 1]);return begin;
}
元素個數小用直接插入排序
void QuickSort(int *array, int left, int right)
{if (right - left < 16)//如果快排的元素個數沒有達到16及其以上,就用插入排序InsertSort(array, right - left);else{int div = Partion(array, left, right);QuickSort(array, left, div);QuickSort(array, div + 1, right);}
}

快速排序非遞歸寫法

#include"stack.h"
//快排非遞歸
void QuickSortNor(int*array, int size)
{int left = 0;int right = size;Stack s;StackInit(&s);StackPush(&s,right);StackPush(&s,left); //后進去的先出來,先出來的是左while (!StackEmpty(&s)){left = StackTop(&s);StackPop(&s);right = StackTop(&s);StackPop(&s);if (left < right){int div = Partion3(array, left, right);//先保存右半部分,先進后出來StackPush(&s,right);//右半部分右邊界StackPush(&s, div + 1);//右半部分左邊界//再保存左邊部分,后進先出來StackPush(&s, div);//左半部分右邊界StackPush(&s, left);//左半部分左邊界}}StackDestroy(&s);
}

歸并排序

歸并排序

基本思想:

歸并排序(MERGE-SORT)是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide andConquer)的一個非常典型的應用。將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合并成一個有序表,稱為二路歸并。
在這里插入圖片描述

歸并排序的特性總結:

  1. 歸并的缺點在于需要O(N)的空間復雜度,歸并排序的思考更多的是解決在磁盤中的外排序問題。
  2. 時間復雜度:O(N*logN)
  3. 空間復雜度:O(N)
  4. 穩定性:穩定

代碼實現

//歸并到temp臨時空間里
//兩個有序序列合并成一個
void MergeData(int*array, int left, int mid, int right, int *temp)
{int begin1 = left, end1 = mid;int begin2 = mid, end2 = right;int index = left;while (begin1 < end1 && begin2 < end2)//第一個和第二個區間里的元素沒有處理完{if (array[begin1] < array[begin2])temp[index++] = array[begin1++];elsetemp[index++] = array[begin2++];}//如果第一個空間里的數沒有搬移完while (begin1 < end1)temp[index++] = array[begin1++];//第一個空間搬移完了,第二個空間里的元素沒有搬移完while (begin2 < end2)temp[index++] = array[begin2++];
}
void _MergeSort(int*array, int left, int right,int*temp)
{//int*temp=(int*)malloc(sizeof(array[left])*(right-left));if (right - left>1) //區間里的元素超過一個,再排序{//找中間位置int mid = left + ((right - left) >> 1);_MergeSort(array, left, mid,temp);_MergeSort(array, mid, right,temp);MergeData(array, left, mid, right, temp);memcpy(array + left, temp + left, sizeof(array[left])*(right - left));}
}
void MergeSort(int *array, int size)
{int *temp = (int*)malloc(size*sizeof(array[0]));if (NULL == temp){assert(0);return;}_MergeSort(array, 0, size, temp);free(temp);
}

歸并排序非遞歸

void MergeSortNor(int *array, int size)
{int *temp = (int*)malloc(size*sizeof(array[0]));if (NULL == temp){assert(0);return;}int gap = 1;while (gap < size){for (int i = 0; i < size; i += 2 * gap){int left = i;//左int mid = left + gap;//中int right = mid + gap;//右if (mid >= size)mid = size;if (right >= size)right = size;MergeData(array, left, mid, right, temp);}memcpy(array, temp, (sizeof(array[0])*size));gap *= 2;}free(temp);
}

非比較排序

思想:計數排序又稱為鴿巢原理,是對哈希直接定址法的變形應用。

在這里插入圖片描述
操作步驟:

  1. 統計相同元素出現次數
  2. 根據統計的結果將序列回收到原來的序列中

在這里插入圖片描述

計數排序的特性總結:

  1. 計數排序在數據范圍集中時,效率很高,但是適用范圍及場景有限
  2. 時間復雜度:O(MAX(N,范圍))
  3. 空間復雜度:O(范圍)
  4. 穩定性:穩定

代碼實現

//場景:數據密集集中在某個范圍中
void CountSort(int*array, int size)
{int minVal = array[0];//范圍的左邊界值int maxVal = array[0];//范圍的右邊界值//1--找數據的范圍for (int i = 1; i < size; ++i){if (array[i] < minVal)minVal = array[i];if (array[i]>maxVal)maxVal = array[i];}//2--計算保存計數的空間int range = maxVal - minVal + 1;int *temp = (int*)malloc(sizeof(int)*range);if (NULL == temp){assert(0);return;}//3---空間位置里全部置為0memset(temp, 0, sizeof(int)*range);//memeset 按一個一個字節賦值,賦值0可以,賦值其他值不行,例如100,給一個字節賦值100//4--統計每個數據出現的次數for (int i = 0; i < size; ++i){temp[array[i] - minVal]++;}//5--回收數據int index = 0;for (int i = 0; i < range; ++i){while (temp[i]--)  //當前元素值不為0,說明該下標還有個數	{array[index++] = i + minVal;}}free(temp);
}

計數排序參考鏈接

排序總結

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383119.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383119.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383119.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

哈希的概念及其操作

哈希概念 順序結構以及平衡樹中&#xff0c;元素關鍵碼與其存儲位置之間沒有對應的關系&#xff0c;因此在查找一個元素時&#xff0c;必須要經過關鍵碼的多次比較。順序查找時間復雜度為O(N)&#xff0c;平衡樹中為樹的高度&#xff0c;即O( Log2N)&#xff0c;搜索的效率取決…

軟件工程---1.概述

軟件的特征 抽象&#xff1a; 不可觸摸&#xff0c;邏輯實體&#xff0c;可記錄&#xff0c;但看不到復制成本低&#xff1a;不受物質材料的限制&#xff0c;不受物理定律或加工過程的制約&#xff0c;與開發成本相比&#xff0c;復制成本很低無折舊、受硬件制約、未完全擺脫手…

軟件工程---2.軟件過程

三個模型 瀑布模型增量模型集成和配置模型 沒有適用于所有不同類型軟件開發的過程模型。 瀑布模型 需求定義系統和軟件的設計實現與單元測試集成與系統測試運行與維護 瀑布模型的特征 從上一項活動中接受該項活動的工作成果&#xff08;工作產品&#xff09;&#xff0c;作…

軟件工程---3.敏捷軟件開發

敏捷軟件開發 極限編程&#xff08;XP&#xff0c; Beck1999&#xff09;Scrum方法&#xff08;Schwaber and Beedle 2001&#xff09;DSDM方法&#xff08;Stapleton 2003&#xff09; 敏捷軟件的開發宣言 個體和交互勝過過程和工具可以工作的軟件勝過面面俱到的文檔客戶合…

軟件工程---4.需求工程

需求工程定義 找出、分析、文檔化并且檢查需求的過程被稱為需求工程 需求的兩個描述層次 用戶需求&#xff0c;指高層的抽象需求。使用自然語言、圖形描述需求。系統需求&#xff0c;指底層的詳細需求。使用系統需求文檔&#xff08;有時被稱為功能規格說明&#xff09;應該…

軟件工程---5.系統建模

從不同視角對系統建模 外部視角&#xff0c;上下文模型&#xff0c;對系統上下文或環境建模交互視角&#xff0c;交互模型&#xff08;功能模型&#xff09;&#xff0c;對系統與參與者或系統內構件之間的交互建模結構視角&#xff0c;結構模型&#xff08;靜態模型&#xff0…

軟件工程---6.體系結構設計

體系結構模型是什么&#xff1f; 體系結構模型&#xff0c;該模型描述系統如何被組織為一組相互通信的構件 體系結構分類 小體系結構關注單個程序的體系結構。在這個層次上&#xff0c;我們關注單個的程序是如何補分解為構件的。大體系結構關注包括其他系統、程序和程序構件…

【劍指offer】_06 變態跳臺階

題目描述 一只青蛙一次可以跳上1級臺階&#xff0c;也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。 解題思路 鏈接&#xff1a;https://www.nowcoder.com/questionTerminal/22243d016f6b47f2a6928b4313c85387 關于本題&#xff0c;前提是…

【劍指offer】_07 矩形覆蓋

題目描述 我們可以用21的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個21的小矩形無重疊地覆蓋一個2*n的大矩形&#xff0c;總共有多少種方法&#xff1f; 解題思路 依舊是斐波那契數列 2n的大矩形&#xff0c;和n個21的小矩形 其中target*2為大矩陣的大小 有以下幾種情形…

軟件工程---07.設計與實現

軟件設計和軟件實現 軟件設計是一個創造性的活動&#xff0c;在此活動中需要基于客戶需求識別軟件構件及其關系。軟件實現是將設計實現為一個程序的過程 為開發一個系統設計&#xff0c;你需要 理解并定義上下文模型以及系統的外部交互設計系統體系結構識別系統中的主要對象…

軟件工程---08.軟件測試

測試 測試的正向思維&#xff08;確認測試&#xff09; 向開發人員和客戶展示軟件滿足其需求測試的逆向思維&#xff08;缺陷測試&#xff09;找出可能導致軟件行為不正確原因。測試是更廣闊的軟件確認和驗證( Verification and Validation; V & V)過程的一部分。驗證和確…

軟件工程---15.軟件復用

復用的圖(牢記) 軟件復用的好處 開發加速有效的專家利用提高可依賴性降低開發成本降低過程風險符合標準 軟件復用的缺點 創建&#xff0c;維護以及使用一個構件庫查找&#xff0c;理解以及適配可復用構件維護成本增加缺少工具支持“不是在這里發明的”綜合癥 應用框架 現在…

軟件工程---16.基于構件的軟件工程

CBSE CBSE是定義、實現、集成或組裝松散耦合的獨立構件成為系統的過程。 基于構件的軟件工程的要素有: 完全由接口進行規格說明的獨立構件。構件標準使構件集成變得更為容易。中間件為構件集成提供軟件支持。開發過程適合基于構件的軟件工程。 CBSE的設計原則 構件是獨立的…

軟件工程---17.分布式軟件工程

分布式系統的5個優點 資源共享開放性并發性可伸縮性容錯性 分布式計算中必須考慮的設計問題 透明性&#xff1a;隱藏底層分布 開放性 可伸縮性 三個維度 規模&#xff1a;又分為增強擴展(單挑)&#xff0c;增加擴展(群毆)分布可靠性 信息安全性 主要防止以下類型的攻擊 攔…

軟件工程---18.面向服務的軟件工程

什么是Web服務 一個松耦合、可復用的軟件構件&#xff0c;封裝了離散的功能&#xff0c;該功能是分布式的并且可以被程序訪問。Web服務是通過標準互聯網和基于XML的協議被訪問的服務。 服務和軟件構件之間的一個重要的區別是 服務應該總是獨立的和松耦合的Web 服務沒有“請求…

【劍指offer】_08.數值的整數次方

題目描述 給定一個double類型的浮點數base和int類型的整數exponent。求base的exponent次方。 保證base和exponent不同時為0 解題思路 首先一個數的任意次方&#xff0c;這個數有可能是負數和正數和零&#xff0c;然后次方也有可能是負數和正數和零 當這個數是零時&#xff…

【劍指offer】_09二叉搜索樹的后序遍歷序列

題目描述 輸入一個整數數組&#xff0c;判斷該數組是不是某二叉搜索樹的后序遍歷的結果。如果是則輸出Yes,否則輸出No。假設輸入的數組的任意兩個數字都互不相同。 解題思路 比如下面的這棵二叉搜索樹 它的后序遍歷為0214369875&#xff1b; 我們設當前根節點為root; 第一次…

【劍指offer】_10二叉樹和為某一路徑值

題目描述 輸入一顆二叉樹的跟節點和一個整數&#xff0c;打印出二叉樹中結點值的和為輸入整數的所有路徑。路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。 解題思路 要求一路徑的和&#xff0c;那么必然終止條件為葉子結點&#xff0c;從根結點出發…

【劍指offer】_11整數中1出現的次數

題目描述 求出1~13的整數中1出現的次數,并算出100~1300的整數中1出現的次數&#xff1f;為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對于后面問題他就沒轍了。ACMer希望你們幫幫他,并把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的…

【劍指offer】_12 數組中的逆序對

題目描述 在數組中的兩個數字&#xff0c;如果前面一個數字大于后面的數字&#xff0c;則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數P。并將P對1000000007取模的結果輸出。 即輸出P%1000000007 解題思路 劍指offer的解法 看到這個題目&#xff0…