排序:
给定的一串随机排列的记录,通过一种调整方法,让其按照某个或某些关键字的大小,形成一种递增或递减的顺序的排布,这种调整方法就叫排序
稳定性
稳定性就是在排序前后,序列中的相对次序没有发生改变,就是稳定的,否则就是不稳定的
也就是某个值在排序前在另一个值前面,经过某种方法排序后还在这个值前面,就说这个排序算法是稳定的
内部排序 & 外部排序
内部排序就是直接将所有数据全部加载进内存中进行排序
外部排序是将数据存放在外部存储设备中,每次排序时将部分数据加载进内存中,一般用于海量数据的排序
插入排序
-
直接插入排序 数据量比较少,接近有序 稳定 时间 O(N^2)
-
希尔排序 在插入排序之前进行一次分组 加了个分组的思想 对插入排序的优化
-
不稳定,因为隔着区间插入了
-
交换排序
-
冒泡排序
-
快速排序: 适合于数据量越大,数据排序越随机,越适合于用快速排序
- 对待排序数据中先找一个基准值(取代排序区间的左右侧),按照基准值将序列分割成左右两部分
- 递归的方法:用快排对左半部分进行排序
- 用快排对右半部分进行排序
快排的三种方法:
-
hoare法
-
挖坑法:在右边找一个基准值,从左边遍历找一个比基准值大的元素放到原基准值的位置
-
前后指针法:左指针向右找比基准值大的元素,右指针向左找比基准值大的元素找到后停下,交换两个指针指向的元素,直到两个指针相遇
-
每次划分:基准值是最大 || 最小的数字 让数据集中到基准值的一侧
-
时间复杂度:最差情况下,是O(N^2) 接近有序 (接近有序时不考虑快排的方案)
空间复杂度:
快排的两种优化:
-
三数取中法:降低了取到极大值和最小值的概率 时间: 空间:O(N)
-
递归到小的子区间时,配合插入排序
递归的深度越深,待排的数据量越小,数据量较小的时候,插入排序的效率更高
选择排序
-
选择排序
-
堆排序: 首先建堆: 要排成升序就建大堆,要排成降序就要建小堆
外部排序:
-
归并排序:类似于快排, 但直接对数据进行划分为左右两半(每次均分),对每个子区间在进行划分,直到子区间有序(当子区间只剩一个数据,子区间肯定有序),有序之后进行归并,合成一个完整区间
(要借助辅助空间)
归并排序没有最好最差情况之分,是一进来直接进行划分,没有去找基准值,而基准值决定了划分的结果
稳定的 ,时间复杂度与快排相同,归并过程是个O(N*log N)的算法,每次进行归并都是均分的
进行n次划分,每次都是均等的二分,log2^N
空间复杂度:O(N) 每次划分都借助了辅助空间
进行划分-》直到每个子区间只有一个元素-》进行归并,两两有序-》两两归并,四四有序-》最终完全归并,整体有序, gap用于记录现在是几个分组有序,当gap大于size,整个数组肯定是有序的
void merge()
{
int* temp=(int*)malloc(size *sizeof(array[0]));
assert(temp);
int temp=1;
}
归并排序适合于做外部排序
非比较排序:
计数排序: (需要知道数据的范围)
-
计数统计每个元素出现的次数
-
对元素进行回收
时间复杂度
空间复杂度:O(M) 空间复杂度由元素范围决定