您好,登錄后才能下訂單哦!
這篇文章主要講解了“C語言歸排與計排是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“C語言歸排與計排是什么”吧!
歸并排序:是創建在歸并操作上的一種有效的排序算法。算法是采用分治法(Divide and Conquer)的一個非常典型的應用,且各層分治遞歸可以同時進行。歸并排序思路簡單,速度僅次于快速排序,為穩定排序算法,一般用于對總體無序,但是各子項相對有序的數列。
1. 基本思想
歸并排序是用分治思想,分治模式在每一層遞歸上有三個步驟:
分解(Divide):將n個元素分成個含n/2個元素的子序列。
解決(Conquer):用合并排序法對兩個子序列遞歸的排序。
合并(Combine):合并兩個已排序的子序列已得到排序結果。
歸并排序的特性總結:
1. 歸并的缺點在于需要O(N)的空間復雜度,歸并排序的思考更多的是解決在磁盤中的外排序題。
2. 時間復雜度:O(N*logN)
3. 空間復雜度:O(N)
4. 穩定性:穩定
這是歸并排序的主要概念。
歸并排序有遞歸和非遞歸兩種,我們首先來實現遞歸的代碼
代碼
//歸并遞歸 void _MergeSore(int* arr, int left, int right, int* tmp) { //遞歸結束條件 if (left >= right) return; //int min = left + ((right - left) >> 1); int min = (left + right) / 2; //遞歸開始 _MergeSore(arr, left, min, tmp); _MergeSore(arr, min + 1, right, tmp); //排序開始 int begin1 = left, end1 = min; int begin2 = min + 1, end2 = right; int i = left; while (begin1 <= end1 && begin2 <= end2) { if (arr[begin1] < arr[begin2]) { tmp[i++] = arr[begin1++]; /*i++; begin1++;*/ } if (arr[begin1] >= arr[begin2]) { tmp[i++] = arr[begin2++]; /*i++; begin2++;*/ } } while (begin1 <= end1) { tmp[i++] = arr[begin1++]; } while (begin2 <= end2) { tmp[i++] = arr[begin2++]; } //將建立的數組拷貝到原數組中 for (int i = 0; i <= right; i++) { arr[i] = tmp[i]; } } //歸并排序 void MergeSort(int* arr, int n) { //先建立一個數組,用來存放排序的元素 int* tmp = (int*)malloc(sizeof(int) * (n)); if (tmp == NULL) { perror("perror,file"); return; } //歸并函數實現 _MergeSore(arr, 0, n - 1, tmp); //銷毀新建數組,防止內存泄漏 free(tmp); //防止野指針 tmp = NULL; }
下面是非遞歸的寫法,非遞歸的思想與遞歸的思想幾乎一樣,大家可以自己想下過程。
申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合并后的序列
設定兩個指針,最初位置分別為兩個已經排序序列的起始位置
比較兩個指針所指向的元素,選擇相對小的元素放入到合并空間,并移動指針到下一位置
重復步驟③直到某一指針到達序列尾
將另一序列剩下的所有元素直接復制到合并序列尾
void _MergeSoreNonR1(int* arr, int left, int right, int* tmp) { int gap = 1; int i = 0; while (gap <= right) { for (i = 0; i <= right; i += 2 * gap) { //[i,I+gap-1] [i+gap,2*gap-1] int begin1 = i, end1 = i + gap - 1; int begin2 = i + gap, end2 = i + 2 * gap - 1; //printf(" %d", end2); if (end1 > right) end1 = right; if (begin2 > right) { begin2 = right + 1; end2 = right; } if (end2 > right) end2 = right; int index = i; while (begin1 <= end1 && begin2 <= end2) { if (arr[begin1] < arr[begin2]) { tmp[index++] = arr[begin1++]; } if (arr[begin1] >= arr[begin2]) { tmp[index++] = arr[begin2++]; } } while (begin1 <= end1) { tmp[index++] = arr[begin1++]; } while (begin2 <= end2) { tmp[index++] = arr[begin2++]; } } for (i = 0; i <= right; i++) { arr[i] = tmp[i]; } gap *= 2; } } void MergeSortNonR(int* arr, int n) { int* tmp = (int*)malloc(sizeof(int) * n); if (tmp == NULL) { perror("malloc,file"); return; } _MergeSoreNonR1(arr, 0, n-1, tmp); free(tmp); tmp = NULL; }
下面來看計數排序
計數排序不用比較兩個數的大小,它的做法是統計哪個元素出現的次數,然后通過這個元素出現的次數來排序。
計數算法只能使用在已知序列中的元素在0-k之間,且要求排序的復雜度在線性效率上。 Â 計數排序和基數排序很類似,都是非比較型排序算法。但是,它們的核心思想是不同的,基數排序主要是按照進制位對整數進行依次排序,而計數排序主要側重于對有限范圍內對象的統計。基數排序可以采用計數排序來實現。
計數排序的特性總結:
1. 計數排序在數據范圍集中時,效率很高,但是適用范圍及場景有限。
2. 時間復雜度:O(MAX(N,范圍))
3. 空間復雜度:O(范圍)
4. 穩定性:穩定
代碼實現
void CountSort(int* arr, int n) { //確定數組開辟的大小 int max = arr[0], min = arr[0]; for (int i = 1; i < n; i++) { if (arr[i] > max) max = arr[i]; if (arr[i] < min) min = arr[i]; } int range = max - min + 1; //建立一個數組 int* count = (int*)malloc(sizeof(int) * range); if (count == NULL) { perror("malloc file"); return NULL; } memset(count, 0, sizeof(int) * range); for (int i = 0; i < n; i++) { count[arr[i]-min]++; } int j = 0; for (int i = 0; i < n; i++) { while (count[i]--) { arr[j] = i+min; j++; } } free(count); count = NULL; }
下面是一張八大排序的比較圖
感謝各位的閱讀,以上就是“C語言歸排與計排是什么”的內容了,經過本文的學習后,相信大家對C語言歸排與計排是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。