1.插入排序
直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移。
直接插入排序的特性总结:
1. 元素集合越接近有序,直接插入排序算法的时间效率越高
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1),它是一种稳定的排序算法
4. 稳定性:稳定
void Insertsort(vector<int>array){
for (int i = 1; i < array.size(); ++i){
int key = array[i];//要插入的元素
int end = i - 1;//找key的插入位置:与前面已经排序好的元素从后往前比较
while (end >= 0 && key< array[end]){
array[end + 1] = array[end];
end--;
}
//插入元素
array[end + 1] = key;
}
}
1.1 希尔排序
希尔排序是插入排序基础上的优化,基本思想是先选定一个整数,将待排序数组中的所有元素分成组(按距离分组),并对每一组内的记录进行排序。重复上述分组和排序的工作,当到达==1时,所有记录已排好序。
希尔排序的特性:
1.是对直接排序的优化。
2.品骏时间复杂度为O(N^1.3-N^2);
3.稳定性:不稳定
void Shellsort(vector<int>array){
int gap = 3;
while (gap>0){
for (int i = gap; i < array.size(); ++i){
int key = array[i];//插入元素
//key的插入位置,与前面排好序的元素从后往前比较
int end = i - gap;
while (end >= 0 && key>array[end]){
array[end + gap] = array[end];
end -= gap;
}
array[end + gap] = key;//插入元素
}
gap--;
}
}
2.选择排序
2.1直接选择排序
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的
数据元素排完 。
在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素
若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素.
直接选择排序的特性总结:
1. 缺陷:进行重复比较
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)
4. 稳定性:不稳定
void Selectsort(vector<int>array){
for (int i = 0; i < array.size() - 1; ++i){
int maxpos = 0;//记录最大元素位置
for (int j = 1; j < array.size() - i; ++j){
if (array[j]>array[maxpos])
maxpos = j;
}
if (maxpos != array.size() - 1 - i)//若不是当前排序最后一个位置,进行交换
swap(array[array.size() - 1 - i], array[maxpos]);
}
}
2.2堆排序
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是
通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。
堆排序的特性:
1. 效率高。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(1)
4. 稳定性:不稳定
//向下调整
void HeapAdjustdown(vector<int>array, int size, int parent){
int child = parent * 2 + 1;
if (child + 1 < size&&array[child] < array[child + 1])
child += 1;//找左右孩子中的较大的
if (array[parent]>array[child]){
swap(array[parent], array[child]);
parent = child;
child = parent * 2 + 1;
}
else return;
}
void Heapsort(vector<int>array){//
//建大堆
int parent = (array.size() - 2) / 2;//找倒数第一个非叶子节点
for (; parent >= 0; parent--)
HeapAdjustdown(array, array.size(), parent);
int end = array.size() - 1;
while (end){//排序,删除方式
swap(array[end], array[0]);//将最大的元素放入最后
HeapAdjustdown(array, end, 0);
end--;
}
}
堆向上调整,用于实现插入元素时
void Heapadjiustup(vector<int>array, int child){
//child为新插入元素下标
int parent = (child - 1) / 2;
while (child){
//当前为大堆,调整元素
if (array[child] < array[parent]){
swap(array[child], array[parent]);
child = parent;
parent = (child - 1) / 2;
}
else return;
}
}
3.交换排序
根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将较大的元素向序列的尾部移动,较小的元素向序列的前部移动。
3.1冒泡排序
特性:
1. 时间复杂度:O(N^2)
2. 空间复杂度:O(1)
3. 稳定性:稳定
void Bubblesort(vector<int>array){
for (int i = 0; i < array.size() - 1; i++){
int flag = 0;//用于判断当前序列是否有序
for (int j = 1; j < array.size() - i; ++j){
//将相邻的两个元素进行交换,使得当前排序最后一个元素为最大
if (array[j - 1]>array[j]){
swap(array[j - 1], array[j]);
flag = 1;
}
}
if (flag == 0) return;//若有序则返回
}
}
3.2快速排序
快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中
的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右
子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
将区间按照基准值划分为左右两半部分的常见方式有:
1. hoare版本
2. 挖坑法
3. 前后指针版本