当前位置:   article > 正文

七大排序经典排序算法_7大排序算法

7大排序算法

吾日三省吾身:高否?富否?帅否?答曰:否。滚去学习!!!(看完这篇文章先)

目前只有C和C++的功底,暂时还未开启新语言的学习,但是大同小异,语法都差不多。

目录:
一.排序定义
二.排序算法的评价指标(最后总结)
1.算法的稳定性
2.时间复杂度和空间复杂度
三.七大排序算法
1.冒泡排序
2.选择排序
3.插入排序
4.希尔排序
5.归并排序
6.快速排序
7.堆排序
稳定性及其复杂度总结

一.排序定义

排序(sort):排序就是重新排列表中的元素,使得元素满足按关键字有序的过程。

二.排序算法的评价指标(最后总结)

1.算法的稳定性

若待排序表中有两个元素R1和R2,其对应的关键字相同即k1= k2,且在排序前R1在R2的前面,若使用某一排序算法排序后,R1仍然在R2的前面,则称这个排序算法是稳定的,否则称排序算法是不稳定的。

意思就是两个相同的关键字在排序前后位置不变,排序前在前面那么排序前就在前面,后面就在后面。

如果排序前后两个数的位置不相同,那么此算法就是不稳定的。

2.时间复杂度和空间复杂度

三.七大排序算法

·排序算法分为内部排序和外部排序,内部排序的时候哦数据都存储在内存中,外部排序中由于数据过多而无法全部放入内存。

  1. 冒泡排序

冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。冒泡排序还有一种优化算法,就是立一个 flag,当在一趟序列遍历中元素没有发生交换,则证明该序列已经有序。

冒泡排序算法步骤:

  1. 从数组的第一个元素开始,依次比较每对相邻的元素,如果前面的元素大于后面的元素,就交换它们的位置。

  1. 对数组中的每一对相邻元素重复步骤1,直到最后一个元素。此时,数组中最后一个元素应该是最大的元素。

  1. 针对除去已排序的最后一个元素的剩余元素,重复步骤1和步骤2,直到整个数组都被排序。

注意:

当输入的数据是正序这个时候排序最快

当输入的数据是反序这个时候排序最慢

C语言实现

  1. #include <stdio.h>
  2. void bubble_sort(int arr[], int len) {
  3. int i, j, temp;
  4. for (i = 0; i < len - 1; i++)
  5. for (j = 0; j < len - 1 - i; j++)
  6. if (arr[j] > arr[j + 1]) {
  7. temp = arr[j];
  8. arr[j] = arr[j + 1];
  9. arr[j + 1] = temp;
  10. }
  11. }
  12. int main() {
  13. int arr[] = { 2, 4, 6, 8, 5, 7,9 , 1,3,10};
  14. int len = (int) sizeof(arr) / sizeof(*arr);
  15. bubble_sort(arr, len);
  16. int i;
  17. for (i = 0; i < len; i++)
  18. printf("%d ", arr[i]);
  19. return 0;
  20. }
'
运行

C++实现

  1. #include <iostream>
  2. using namespace std;
  3. template<typename T> //整数或浮点数皆可使用,若要使用类(class)或结构体(struct)时必须重载大于(>)运算符
  4. void bubble_sort(T arr[], int len) {
  5. int i, j;
  6. for (i = 0; i < len - 1; i++)
  7. for (j = 0; j < len - 1 - i; j++)
  8. if (arr[j] > arr[j + 1])
  9. swap(arr[j], arr[j + 1]);
  10. }
  11. int main() {
  12. int arr[] = {2, 4, 6, 8, 5, 7,9 , 1,3,10 };
  13. int len = (int) sizeof(arr) / sizeof(*arr);
  14. bubble_sort(arr, len);
  15. for (int i = 0; i < len; i++)
  16. cout << arr[i] << ' ';
  17. cout << endl;
  18. return 0;
  19. }
时间复杂度:最坏情况:O(N^2)
      最好情况:O(N)
空间复杂度:O(1)
2.选择排序

选择排序(Selection Sort)是一种简单的排序算法。其基本思想是首先从未排序的元素中找到最小的元素,然后将其放到已排序的序列末尾,然后再从剩余未排序的元素中继续找到最小的元素,将其放到已排序的序列末尾,以此类推,直到所有元素都排好序。

选择排序的算法步骤

  1. 遍历待排序的数组,从第一个元素开始

  1. 在未排序的元素中找到最小的元素,记录其下标

  1. 将最小的元素与第一个元素交换位置

  1. 接着在未排序的元素中继续寻找最小的元素,记录其下标

  1. 将最小的元素与第二个元素交换位置

  1. 重复步骤 4-5 直到所有元素都排序完成

C语言实现

  1. void swap(int *a,int *b) //交换两个数
  2. {
  3. int temp = *a;
  4. *a = *b;
  5. *b = temp;
  6. }
  7. void selection_sort(int arr[], int len)
  8. {
  9. int i,j;
  10. for (i = 0 ; i < len - 1 ; i++)
  11. {
  12. int min = i;
  13. for (j = i + 1; j < len; j++) //走访未排序的元素
  14. if (arr[j] < arr[min]) //找到目前最小值
  15. min = j; //记录最小值
  16. swap(&arr[min], &arr[i]); //做交換
  17. }
  18. }

C++实现

  1. template<typename T>
  2. void selection_sort(std::vector<T>& arr) {
  3. for (int i = 0; i < arr.size() - 1; i++) {
  4. int min = i;
  5. for (int j = i + 1; j < arr.size(); j++)
  6. if (arr[j] < arr[min])
  7. min = j;
  8. std::swap(arr[i], arr[min]);
  9. }
  10. }
3.插入排序

插入排序(Insertion Sort)排序算法,其思想是从第二个元素开始依次将其插入到已经有序的序列中。

插入排序的算法步骤

1第二个元素开始,将该元素视为一个有序序列。

2将该元素与它前面的元素进行比较,如果前面的元素比它大,则交换位置。

3继续向前比较,直到该元素找到了合适的位置。

4对下一个元素重复上述过程,直到所有元素都排好序为止。

C语言实现

  1. void insertion_sort(int arr[], int len){
  2. int i,j,key;
  3. for (i=1;i<len;i++){
  4. key = arr[i];
  5. j=i-1;
  6. while((j>=0) && (arr[j]>key)) {
  7. arr[j+1] = arr[j];
  8. j--;
  9. }
  10. arr[j+1] = key;
  11. }
  12. }

C++实现

  1. void insertion_sort(int arr[],int len){
  2. for(int i=1;i<len;i++){
  3. int key=arr[i];
  4. int j=i-1;
  5. while((j>=0) && (key<arr[j])){
  6. arr[j+1]=arr[j];
  7. j--;
  8. }
  9. arr[j+1]=key;
  10. }
  11. }
时间复杂度:最坏情况下为O(N*N),此时待排序列为逆序,或者说接近逆序
      最好情况下为O(N),此时待排序列为升序,或者说接近升序。
空间复杂度:O(1)
4.希尔排序

希尔排序(Shell Sort)是插入排序的一种改进版本,也被称为“缩小增量排序”。它的基本思想是先将待排序的序列分割成若干个子序列,对每个子序列进行插入排序,然后逐步缩小子序列的长度,最终完成排序。

算法步骤

1.选择一个增量序列 t1,t2,……,tk,其中 ti > tj, t k = 1;

2.按增量序列个数 k,对序列进行 k 趟排序;

3.每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插 入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

C语言实现

  1. void shell_sort(int arr[], int len) {
  2. int gap, i, j;
  3. int temp;
  4. for (gap = len >> 1; gap > 0; gap >>= 1)
  5. for (i = gap; i < len; i++) {
  6. temp = arr[i];
  7. for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap)
  8. arr[j + gap] = arr[j];
  9. arr[j + gap] = temp;
  10. }
  11. }

C++实现

  1. template<typename T>
  2. void shell_sort(T array[], int length) {
  3. int h = 1;
  4. while (h < length / 3) {
  5. h = 3 * h + 1;
  6. }
  7. while (h >= 1) {
  8. for (int i = h; i < length; i++) {
  9. for (int j = i; j >= h && array[j] < array[j - h]; j -= h) {
  10. std::swap(array[j], array[j - h]);
  11. }
  12. }
  13. h = h / 3;
  14. }
  15. }
时间复杂度平均:O(N^1.3)
空间复杂度:O(1)
5.归并排序

归并排序(Merge Sort)是一种分治算法,其基本思想是将待排序序列分成若干个子序列,分别进行排序,然后将子序列合并成一个有序序列。

归并排序算法步骤:

  1. 将待排序序列分成两个子序列,分别进行递归排序。

  1. 合并两个有序子序列,得到一个更长的有序序列。

  1. 重复上述过程,直到所有子序列都有序。

  1. int min(int x, int y) {
  2. return x < y ? x : y;
  3. }
  4. void merge_sort(int arr[], int len) {
  5. int *a = arr;
  6. int *b = (int *) malloc(len * sizeof(int));
  7. int seg, start;
  8. for (seg = 1; seg < len; seg += seg) {
  9. for (start = 0; start < len; start += seg * 2) {
  10. int low = start, mid = min(start + seg, len), high = min(start + seg * 2, len);
  11. int k = low;
  12. int start1 = low, end1 = mid;
  13. int start2 = mid, end2 = high;
  14. while (start1 < end1 && start2 < end2)
  15. b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
  16. while (start1 < end1)
  17. b[k++] = a[start1++];
  18. while (start2 < end2)
  19. b[k++] = a[start2++];
  20. }
  21. int *temp = a;
  22. a = b;
  23. b = temp;
  24. }
  25. if (a != arr) {
  26. int i;
  27. for (i = 0; i < len; i++)
  28. b[i] = a[i];
  29. b = a;
  30. }
  31. free(b);
  32. }

C++实现

  1. template<typename T>
  2. void merge_sort(T arr[], int len) {
  3. T *a = arr;
  4. T *b = new T[len];
  5. for (int seg = 1; seg < len; seg += seg) {
  6. for (int start = 0; start < len; start += seg + seg) {
  7. int low = start, mid = min(start + seg, len), high = min(start + seg + seg, len);
  8. int k = low;
  9. int start1 = low, end1 = mid;
  10. int start2 = mid, end2 = high;
  11. while (start1 < end1 && start2 < end2)
  12. b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
  13. while (start1 < end1)
  14. b[k++] = a[start1++];
  15. while (start2 < end2)
  16. b[k++] = a[start2++];
  17. }
  18. T *temp = a;
  19. a = b;
  20. b = temp;
  21. }
  22. if (a != arr) {
  23. for (int i = 0; i < len; i++)
  24. b[i] = a[i];
  25. b = a;
  26. }
  27. delete[] b;
  28. }

C++(递归版)

  1. void Merge(vector<int> &Array, int front, int mid, int end) {
  2. // preconditions:
  3. // Array[front...mid] is sorted
  4. // Array[mid+1 ... end] is sorted
  5. // Copy Array[front ... mid] to LeftSubArray
  6. // Copy Array[mid+1 ... end] to RightSubArray
  7. vector<int> LeftSubArray(Array.begin() + front, Array.begin() + mid + 1);
  8. vector<int> RightSubArray(Array.begin() + mid + 1, Array.begin() + end + 1);
  9. int idxLeft = 0, idxRight = 0;
  10. LeftSubArray.insert(LeftSubArray.end(), numeric_limits<int>::max());
  11. RightSubArray.insert(RightSubArray.end(), numeric_limits<int>::max());
  12. // Pick min of LeftSubArray[idxLeft] and RightSubArray[idxRight], and put into Array[i]
  13. for (int i = front; i <= end; i++) {
  14. if (LeftSubArray[idxLeft] < RightSubArray[idxRight]) {
  15. Array[i] = LeftSubArray[idxLeft];
  16. idxLeft++;
  17. } else {
  18. Array[i] = RightSubArray[idxRight];
  19. idxRight++;
  20. }
  21. }
  22. }
  23. void MergeSort(vector<int> &Array, int front, int end) {
  24. if (front >= end)
  25. return;
  26. int mid = (front + end) / 2;
  27. MergeSort(Array, front, mid);
  28. MergeSort(Array, mid + 1, end);
  29. Merge(Array, front, mid, end);
  30. }
6.快速排序

快速排序(Quick Sort)是一种常用的排序算法,也是一种分治算法。其基本思想是选择一个基准元素,将待排序序列分成两个子序列,使得一个子序列中所有元素都比基准元素小,另一个子序列中所有元素都比基准元素大,然后递归地对子序列进行排序。

具体实现过程如下:

  1. 选择一个基准元素,一般选择第一个元素或者随机选择一个元素。

  1. 将序列中所有比基准元素小的元素放在基准元素的左边,所有比基准元素大的元素放在右边。

  1. 对基准元素的左右两边重复上述过程,直到每个子序列只剩下一个元素。

C语言实现

  1. typedef struct _Range {
  2. int start, end;
  3. } Range;
  4. Range new_Range(int s, int e) {
  5. Range r;
  6. r.start = s;
  7. r.end = e;
  8. return r;
  9. }
  10. void swap(int *x, int *y) {
  11. int t = *x;
  12. *x = *y;
  13. *y = t;
  14. }
  15. void quick_sort(int arr[], const int len) {
  16. if (len <= 0)
  17. return;
  18. Range r[len];
  19. int p = 0;
  20. r[p++] = new_Range(0, len - 1);
  21. while (p) {
  22. Range range = r[--p];
  23. if (range.start >= range.end)
  24. continue;
  25. int mid = arr[(range.start + range.end) / 2];
  26. int left = range.start, right = range.end;
  27. do {
  28. while (arr[left] < mid) ++left;
  29. while (arr[right] > mid) --right;
  30. if (left <= right) {
  31. swap(&arr[left], &arr[right]);
  32. left++;
  33. right--;
  34. }
  35. } while (left <= right);
  36. if (range.start < right) r[p++] = new_Range(range.start, right);
  37. if (range.end > left) r[p++] = new_Range(left, range.end);
  38. }
  39. }

C++实现

  1. int Paritition1(int A[], int low, int high) {
  2. int pivot = A[low];
  3. while (low < high) {
  4. while (low < high && A[high] >= pivot) {
  5. --high;
  6. }
  7. A[low] = A[high];
  8. while (low < high && A[low] <= pivot) {
  9. ++low;
  10. }
  11. A[high] = A[low];
  12. }
  13. A[low] = pivot;
  14. return low;
  15. }
  16. void QuickSort(int A[], int low, int high) //快排母函数
  17. {
  18. if (low < high) {
  19. int pivot = Paritition1(A, low, high);
  20. QuickSort(A, low, pivot - 1);
  21. QuickSort(A, pivot + 1, high);
  22. }
  23. }

7.堆排序

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:

  1. 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;

  1. 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;

算法步骤

1创建一个堆 H[0……n-1];

2把堆首(最大值)和堆尾互换;

3把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;

4重复步骤 2,直到堆的尺寸为 1。

C语言代码实现

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. void swap(int *a, int *b) {
  4. int temp = *b;
  5. *b = *a;
  6. *a = temp;
  7. }
  8. void max_heapify(int arr[], int start, int end) {
  9. // 建立父節點指標和子節點指標
  10. int dad = start;
  11. int son = dad * 2 + 1;
  12. while (son <= end) { // 若子節點指標在範圍內才做比較
  13. if (son + 1 <= end && arr[son] < arr[son + 1]) // 先比較兩個子節點大小,選擇最大的
  14. son++;
  15. if (arr[dad] > arr[son]) //如果父節點大於子節點代表調整完畢,直接跳出函數
  16. return;
  17. else { // 否則交換父子內容再繼續子節點和孫節點比較
  18. swap(&arr[dad], &arr[son]);
  19. dad = son;
  20. son = dad * 2 + 1;
  21. }
  22. }
  23. }
  24. void heap_sort(int arr[], int len) {
  25. int i;
  26. // 初始化,i從最後一個父節點開始調整
  27. for (i = len / 2 - 1; i >= 0; i--)
  28. max_heapify(arr, i, len - 1);
  29. // 先將第一個元素和已排好元素前一位做交換,再重新調整,直到排序完畢
  30. for (i = len - 1; i > 0; i--) {
  31. swap(&arr[0], &arr[i]);
  32. max_heapify(arr, 0, i - 1);
  33. }
  34. }
  35. int main() {
  36. int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 };
  37. int len = (int) sizeof(arr) / sizeof(*arr);
  38. heap_sort(arr, len);
  39. int i;
  40. for (i = 0; i < len; i++)
  41. printf("%d ", arr[i]);
  42. printf("\n");
  43. return 0;
  44. }
'
运行

C++实现

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. void max_heapify(int arr[], int start, int end) {
  5. //建立父节点和字节点
  6. int dad = start;
  7. int son = dad * 2 + 1;
  8. while (son <= end) {
  9. if (son + 1 <= end && arr[son] < arr[son + 1]) // 比较两个子节点大小,选择大的
  10. son++;
  11. if (arr[dad] > arr[son]) // 如果父节点大于子节点代表完整,退出函数
  12. return;
  13. else {
  14. swap(arr[dad], arr[son]);
  15. dad = son;
  16. son = dad * 2 + 1;
  17. }
  18. }
  19. }
  20. void heap_sort(int arr[], int len) {
  21. for (int i = len / 2 - 1; i >= 0; i--)
  22. max_heapify(arr, i, len - 1);
  23. for (int i = len - 1; i > 0; i--) {
  24. swap(arr[0], arr[i]);
  25. max_heapify(arr, 0, i - 1);
  26. }
  27. }
  28. int main() {
  29. int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 };
  30. int len = (int) sizeof(arr) / sizeof(*arr);
  31. heap_sort(arr, len);
  32. for (int i = 0; i < len; i++)
  33. cout << arr[i] << ' ';
  34. cout << endl;
  35. return 0;
  36. }

稳定性以及复杂度

大话数据结构关于排序算法的的总结:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/1000454
推荐阅读
相关标签
  

闽ICP备14008679号