算法概述
常见的排序算可以分为以下两类:
- 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于时间复杂度不能突破nlogn,因此称为非线性时间比较类排序
- 线性时间非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下限,以线性时间运行,因此称为线性时间非比较类排序
排序相关概念: - 稳定:如果a原本在b的前面,且a=b,排序之后a仍然在b的前面
- 不稳定:如果a原本在b的前面,且a=b,排序之后可能出现在b的后面
一、快速排序
快速排序(Quicksort)是对冒泡排序的一种改进。
快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
排序流程
- 首先设定一个分界值,通过该分界值将数组分成左右两个部分
- 将大于或等于分界值得数据集中到数组右边,小于分界值得数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
- 然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成两部分,同样在左边放置较小值,右边放置较大值,右侧的数据数据也可以做类似的处理
- 重复上述过程,可以看出,这是一个递归定义,通过递归将左侧部分排好序后,再递归排好右侧部分的顺序,当左右两侧部分数据排序完成后,整个数组的排序也就完成了。
C++语言 #include <iostream> using namespace std; void Qsort(int arr[], int low, int high){ if (high <= low) return; int i = low; int j = high + 1; int key = arr[low]; while (true) { /*从左向右找比key大的值*/ while (arr[++i] < key) { if (i == high){ break; } } /*从右向左找比key小的值*/ while (arr[--j] > key) { if (j == low){ break; } } if (i >= j) break; /*交换i,j对应的值*/ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } /*中枢值与j对应值交换*/ int temp = arr[low]; arr[low] = arr[j]; arr[j] = temp; Qsort(arr, low, j - 1); Qsort(arr, j + 1, high); } int main() { int a[] = {57, 68, 59, 52, 72, 28, 96, 33, 24}; Qsort(a, 0, sizeof(a) / sizeof(a[0]) - 1);/*这里原文第三个参数要减1否则内存越界*/ for(int i = 0; i < sizeof(a) / sizeof(a[0]); i++) { cout << a[i] << ""; } return 0; }
def quick_sort(data): """快速排序""" if len(data) >= 2: # 递归入口及出口 mid = data[len(data)//2] # 选取基准值,也可以选取第一个或最后一个元素 left, right = [], [] # 定义基准值左右两侧的列表 data.remove(mid) # 从原始数组中移除基准值 for num in data: if num >= mid: right.append(num) else: left.append(num) return quick_sort(left) + [mid] + quick_sort(right) else: return data # 示例: array = [2,3,5,7,1,4,6,15,5,2,7,9,10,15,9,17,12] print(quick_sort(array)) # 输出为[1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]
快速排序算法的思想很好理解,排序性能不错,但是代码不易实现,还需要进行递归
二、冒泡排序
它重复的走访过要排序的元素列,依次比较两个相邻元素,如果顺序错误,就将他们交换过来,走访元素的工作是重复的进行直到没有相邻元素需要交换,说明排序已完成
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
算法原理
- 比较相邻的元素,如果第一个比第二个大,就交换他们两个
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对,最后的元素应该是最大的数
- 针对多有元素重复以上的步骤,除了最后一个
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
def bubble_sort(nums): for i in range(len(nums) - 1): # 这个循环负责设置冒泡排序进行的次数 for j in range(len(nums) - i - 1): # j为列表下标 if nums[j] > nums[j + 1]: nums[j], nums[j + 1] = nums[j + 1], nums[j] return nums print(bubble_sort([45, 32, 8, 33, 12, 22, 19, 97])) # 输出:[8, 12, 19, 22, 32, 33, 45, 97]
#include <iostream> using namespace std; template<typename T> //整数或浮点数皆可使用 void bubble_sort(T arr[], int len) { int i, j; T temp; for (i = 0; i < len - 1; i++) for (j = 0; j < len - 1 - i; j++) //如果反向排序,此处j可以等于i if (arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } int main() { int arr[] = { 61, 17, 29, 22, 34, 60, 72, 21, 50, 1, 62 }; int len = (int) sizeof(arr) / sizeof(*arr); bubble_sort(arr, len); for (int i = 0; i < len; i++) cout << arr[i] << ' '; cout << endl; float arrf[] = { 17.5, 19.1, 0.6, 1.9, 10.5, 12.4, 3.8, 19.7, 1.5, 25.4, 28.6, 4.4, 23.8, 5.4 }; len = (int) sizeof(arrf) / sizeof(*arrf); bubble_sort(arrf, len); for (int i = 0; i < len; i++) cout << arrf[i] << ' '; return 0; }
冒泡排序实现较为简单,但是性能一般,最差的时间复杂度为o(n²)
三、选择排序
选择排序是一种简单直观的排序算法,它的工作原理是:第一从待排序的数据元素中选出最小的一个元素,放在序列的起始位置,然后从剩余未排序元素中寻找到最小元素,然后放到已排序的序列的末尾,直到全部待排序的数据元素的个数为零,选择排序为不稳定排序。
#include<iostream> #include<time.h> #include<iomanip> using namespace std; const int N=10; int main() { int a[N],i,j,temp,b; srand(time(NULL)); for(i=0;i<N;i++) a[i]=rand()%100; for(i=0;i<N;i++) cout<<setw(3)<<a[i]; cout<<endl; for(i=0;i<N-1;i++) { temp=i; for(j=i+1;j<N;j++) { if(a[temp]>a[j]) temp=j; } if(i!=temp) { b=a[temp]; a[temp]=a[i]; a[i]=b; } } for(i=0;i<N;i++) cout<<setw(3)<<a[i]; cout<<endl; }
def selection_sort(list2): for i in range(0, len (list2)-1): min_ = i for j in range(i + 1, len(list2)): if list2[j] < list2[min_]: min_ = j list2[i], list2[min_] = list2[min_], list2[i] # swap
注意区分冒泡排序和选择排序的区别,冒泡排序是从头开始遍历与相邻元素的大小关系,两层循环遍历就可以实现排序,选择排序是每次记住最小值的位置,注意记住的是最小值的位置,然后放置在合适的位置
来源:https://www.cnblogs.com/hj-SAMA/p/12269187.html