插入排序
基本思想
将数组的第一个数认为是有序数组,从后往前(从前往后)扫描该有序数组,把数组中其余n-1个数,根据数值的大小,插入到有序数组中,直至数组中的所有数有序排列为止。这样的话,n个元素需要进行n-1趟排序!!!
关键点
1、采用双层循环:时间复杂度也是O(n的平方)
(1)外层循环表示的是排序的趟数,n个数字需要n-1趟,因此,外层循环的次数是n-1次;同时也代表数的位置。
(2)内层循环表示的是每一趟排序的数字。根据插入排序的思想,第i趟排序时,有序数组中的数字就有i个,就需要进行i次比较,因此循环i次。注意采用的是从后往前进行比较。
2、从后往前扫描的时候,如果必须插入的数大于有序数组中当前位置的数,则有序数组中的数和它之后的数均往后移一个位置,否则,把插入的数插入到有序数组中。(稳定排序)
#include<iostream>
using namespace std;
void Insertsort(int* array, int n)
{
int i, j, temp;
for (i = 1; i < n; i++)
{
///第一个元素已经放入作为已排序序列的第一个元素
temp = array[i];///依次取出未排序序列的第一个元素
for (j = i; j >= 1 && array[j - 1] > temp; j--)
{
///依次与已排序序列中元素比较并右移
array[j] = array[j - 1];
}
///此时j处腾空,放入待排序元素
array[j] = temp;
}
}
int main()
{
int n;
cin >> n;
int* array = new int[n];
for (int i = 0; i < n; i++)
cin >> array[i];
Insertsort(array,n);
delete[]array;
return 0;
}
希尔排序
基本思想
希尔排序是插入排序的一种改进,主要是为了解决当较小的数据大都出现在数组后面时导致的移动次数明显增多的问题,思想是使用一个不断缩小的增量gap将数组元素分组,在每个分组内部先进行插入排序,当gap减少到1时整个数组元素分在一组,最后进行一次插入排序,整个排序过程结束。
关键点
算法时间复杂度:最好情况:当数据已经排好序的情况下:O(N^1.3);
最坏情况:O(N^2);平均情况:O(NlogN)
算法空间复杂度:O(1)
算法稳定性:不稳定
#include<iostream>
using namespace std;
//完全仿照直插排序,把1改成gap
void Shellsort(int* list, int n)
{
int i, j, gap;
int temp;
相对于插入排序,多了gap的这一层循环
for (gap = n / 2; gap > 0; gap /= 2) ///分组排序
{
for (i = gap; i < n; i++)
{
temp = list[i];
for (j = i; j >= gap && list[j - gap] < temp; j -= gap)
list[j] = list[j - gap];
list[j] = temp;
}
}
}
快速排序
基本思想
我们要知道,快速排序其实是冒泡排序的一种改进,冒泡排序每次对相邻的两个数进行比较,这显然是一种比较浪费时间的。而快速排序是分别从两端开始”探测”的,先找一个关键字(一般选取线性表的第一个元素),再分别先从右往左找一个小于关键字的数,从左往右找一个大于关键字的数,然后交换他们。这里可以用两个指针low和high,分别指向线性表最左边和最右边。low指针找大于关键字的元素,high指针找小于关键字的元素,找到后交换两元素。一直循环上述过程,直到low指针等于high指针,说明这个位置就是分界线,分界线左边元素均小于关键字,右边元素均大于关键字。将关键字和这个位置的元素交换,关键字就在分界线的位置上了(即关键字排好了序)。接下来只需要对关键字左右两边子序列重复上述操作即可(递归),最后得到排好序的线性表。
关键点
void Quick_Sort(int *arr, int begin, int end){
//确定递归出口
if(begin > end)
return;
int pivok = arr[begin]; //选择第一个元素为关键字
int low = begin;
int high = end;
while(low != high){
//high指针找小于pivok的元素
while(arr[high] >= pivok && high > low)
high--;
//low指针找大于pivok的元素
while(arr[low] <= pivok && high > low)
low++;
if(high > low) //要排除high = low 的情况
swap(arr[high],arr[low]);
}
// high = low即为分界线,分界线左边元素均小于pivok,
// 右边元素均大于pivok
swap(arr[begin],arr[high]);
Quick_Sort(arr, begin, high - 1); //对关键字左边的子序列再快排
Quick_Sort(arr, high + 1, end); //对关键字右边的子序列再快排
}