排序算法

性质

稳定性

稳定性是指相等的元素经过排序之后的相对顺序是否发生了改变。拥有稳定性这一特性的算法会让原本相等键值的记录维持相对次序不变。如果一个排序算法是稳定的,那么对相等键值的数据R和S,如果R出现在S之前,那么在排序过的列表中R也会在S之前
稳定排序:基数排序、计数排序、冒泡排序、归并排序
非稳定排序:选择排序、堆排序、快速排序和希尔排序

选择排序

遍历列表,每次都和当前最小(最大)的元素进行交换

  1. void selection_sort(vector<int> v)
  2. {
  3. int n = v.size();
  4. int total = 0;
  5. for (int i = 0; i < n - 1; i++)
  6. {
  7. int minIndex = i;
  8. for (int j = i + 1; j < n; j++)
  9. {
  10. if (v[j] < v[minIndex])
  11. {
  12. total++;
  13. minIndex = j;
  14. }
  15. }
  16. swap(v[i], v[minIndex]);
  17. }
  18. cout << "***************选择排序...****************" << endl;
  19. for (auto &item : v)
  20. {
  21. cout << item << " ";
  22. }
  23. cout << endl;
  24. cout << "总共比较次数为:" << total << endl;
  25. }

冒泡排序

每次都将邻近的两个元素进行比较,并按照规则进行交换 另外,一般来说是要对每一个元素都进行遍历,并交换,但在最坏的情况下:比如序列原本就已经升序,那么我们就不需要再重复循环,优化后的代码如下:

  1. void bubble_sort(vector<int> v)
  2. {
  3. int n = v.size();
  4. int total = 0;
  5. bool flag = true;
  6. while (flag)
  7. {
  8. flag = false;
  9. for (int i = 0; i < n - 1; i++)
  10. {
  11. if (v[i] > v[i + 1])
  12. {
  13. flag = true;
  14. swap(v[i], v[i + 1]);
  15. total++;
  16. }
  17. }
  18. }
  19. cout << "***************冒泡排序...****************" << endl;
  20. for (auto &item : v)
  21. {
  22. cout << item << " ";
  23. }
  24. cout << endl;
  25. cout << "总共比较次数为:" << total << endl;
  26. }

插入排序

  1. void insert_sort(vector<int> v)
  2. {
  3. int n = v.size();
  4. int total = 0;
  5. for (int i = 1; i < n; i++)
  6. {
  7. int temp = v[i];
  8. int j = i - 1;
  9. while (j >= 0 && v[j] > temp)
  10. {
  11. v[j + 1] = v[j];
  12. j--;
  13. total++;
  14. }
  15. v[j + 1] = temp;
  16. }
  17. cout << "***************插入排序...****************" << endl;
  18. for (auto &item : v)
  19. {
  20. cout << item << " ";
  21. }
  22. cout << endl;
  23. cout << "总共比较次数为:" << total << endl;
  24. }

快速排序

找出一个基准数m,其左边的数全部小于m,右边的数全部大于m

  1. void quick_sort(vector<int> v)
  2. {
  3. function<void(vector<int> &, int, int)> quick_sort_oper = [&](vector<int> &v, int left, int right)
  4. {
  5. if (left >= right)
  6. {
  7. return;
  8. }
  9. int i = left;
  10. int j = right;
  11. int key = v[left];
  12. while (i < j)
  13. {
  14. while (i < j && v[j] >= key)
  15. {
  16. j--;
  17. }
  18. while (i < j && v[i] <= key)
  19. {
  20. i++;
  21. }
  22. swap(v[i], v[j]);
  23. }
  24. swap(v[left], v[i]);
  25. quick_sort_oper(v, left, i - 1);
  26. quick_sort_oper(v, i + 1, right);
  27. };
  28. quick_sort_oper(v, 0, v.size() - 1);
  29. for (auto &item : v)
  30. {
  31. cout << item << " ";
  32. }
  33. cout << endl;
  34. }

桶排序

用一个静态长度的数组来模拟一个桶,如果输入的列表中存在这个数,那么就在对应桶中放入一个数 最后再遍历每一个桶,由于遍历的时候是按照下标顺序(下标顺序其实就是每一个数的顺序),从而可以实现排序 这种排序方式很快,但是很耗费空间(数据量多大,就要开多大的空间)

  1. void bucket_sort(vector<int> v)
  2. {
  3. int n = v.size();
  4. vector<int> bucket(10001, 0);
  5. int maxEle = *max_element(v.begin(), v.end());
  6. for (int i = 0; i < v.size(); i++)
  7. {
  8. bucket[v[i]]++;
  9. }
  10. for (int i = 0; i < maxEle; i++)
  11. {
  12. if (bucket[i] != 0)
  13. {
  14. cout << i << " ";
  15. }
  16. }
  17. }