(1)直接插入排序
基本思想:将第一个序列看成已经有序的自序列,从第二个序列起依次进行插入,使得整个序列集体有序。
时间复杂度为O(n^2),空间复杂度为O(1),稳定。
特点:越有序越快,在所有元素全部有序的情况下时间复杂度为O(n)。
代码如下:
void InsertSort(int *arr,int len)
{
int i;
int j;
int tmp;
for(i=1;i<len;i++)
{
tmp = arr[i];
for(j=i-1;j>=0;j--)
{
if(arr[j] > tmp)
arr[j+1] = arr[j];
else
break;
}
arr[j+1] = tmp;
}
}
void test(int []arr,int len)
{
if (arr == null)
return;
for(int i=1;i<len;++i)
{
int temp = arr[i];
int j = I;
while(arr[j-1]>temp)
{
arr[j] = arr[j - 1];
j--;
}
arr[j] = temp;
}
}
(2)希尔排序
基本思想是:将整个待排序列分为若干子序列,分别进行直接插入排序,待整个待排序列基本有序时,再对所有序列进行一次直接插入排序。
时间复杂度为O(N^1.3)--O(N^1.5)之间,空间复杂度为O(1),不稳定。
代码如下:
static void Shell(int *arr,int len,int gap)//gap是分几组,步长
{
int i;
int j;
int tmp;
for(i=gap;i<len;i++)
{
tmp = arr[i];
for(j=i-gap;j>=0;j-=gap)
{
if(arr[j] > tmp)
arr[j+gap] = arr[j];
else
break;
}
arr[j+gap] = tmp;
}
}
void ShellSort(int *arr,int len)
{
int d[] = {5,3,1};
for(int i=0;i<sizeof(d)/sizeof(d[0]);i++)
{
Shell(arr,len,d[i]);
}
}
(3)冒泡排序
基本思想:经过一趟比较将最大的数(最小的数)放在最后一个,依次进行多趟比较,每一次确定一个.(相邻的两个待排序列
比较)。
时间复杂度是O(n^2),空间复杂度是O(1),稳定
优化:当所有数据都有序时,它的时间复杂度仍然是O(n^2),那么可以增加一个状态量表示有没有数据交换,如果有则继
续,无则说明数据已经全部有序了。
代码如下:
void BubbleSort(int *arr,int len)
{
int tmp;
for(int i=1;i<len;i++)
{
for(int j=0;j<len-i;j++)
{
if(arr[j] > arr[j+1])
{
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
(4)快速排序
基本思想:通过一次排序将待排记录分割成独立的两部分,其中一部分的所有关键字都小于另一部分的关键字,再依次对这两部分记录继续进行排序,以达整个序列有序。
特点:当数据有序时退化为选择排序,时间复杂度为O(n^2).越有序越慢。
时间复杂度是O(nlogN),空间复杂度是O(logN),不稳定。
代码如下:
static int Partition(int *arr,int low,int high)
{
int tmp = arr[low];
while(low < high)
{
while((low<high) && (arr[high]>=tmp))
high--;
if(low < high)
arr[low] = arr[high];
else
break;
while((low<high) && (arr[low]<=tmp))
low++;
if(low < high)
arr[high] = arr[low];
else
break;
}
arr[low] = tmp;
return low;
}
void QuickSort1(int *arr,int len)
{
int par = Partition(arr,0,len-1);
int low = 0;
int high = len-1;
if(low+1<par)
QuickSort1(arr,par-low);
if(par+1<high)
QuickSort1(arr+par+1,high-par);
}
(5)选择排序
基本思想:从待排序的元素序列中选择关键字最小或最大的元素,将其放在已排序元素序列的最前面或最后面,其余的元素构成新的待排序元素序列,并从待排序元素序列中选择关键字最小的元素,将其放在待排序元素序列的最前面或最后面。
时间复杂度是O(n^2),空间复杂度是O(1),不稳定
优化:锦标排序
代码如下:
void SelectSort(int *arr,int len)//选择排序
{
int index;//存放每次找的最小值的下标
int tmp;
for(int i=0;i<len;i++)
{
index = i;//每次以I为基准,从i+1开始找
for(int j=i+1;j<len;j++)
{
if(arr[j] < arr[index])
index = j;
}
if(index != i)
{
tmp = arr[i];
arr[i] = arr[index];
arr[index] = tmp;
}
}
}
(6)堆排序
建立大根堆的时间复杂度是O(nlogN),堆排序的时间复杂度是O(nlogN),空间复杂度是O(1),不稳定。
代码如下:
void HeapAdjust(int *arr,int start,int end)
{
int tmp = arr[start];
int parent = start;
for(int i=2*parent+1;i<=end;i=2*i+1)
{
if((i+1<=end) && (arr[i]<arr[i+1]))
{
++i;
}//i一定是左右孩子较大值的下标
if(tmp < arr[i])
{
arr[parent] = arr[i];
parent = i;
}
else
break;
}
arr[parent] = tmp;
}
void HeapSort(int *arr,int len)//O(nlogn),O(1),不稳定
{
int i;
int tmp;
for(i=(len-1-1)/2;i>=0;i--)//O(nlogn)
{
HeapAdjust(arr,i,len-1);
}
for(i=0;i<len-1;i++)//O(nlogn)
{
tmp = arr[0];
arr[0] = arr[len-1-i];
arr[len-1-i] = tmp;
HeapAdjust(arr,0,len-i-1-1);
}
}
(7)归并排序
基本思想是:将两个或两个以上的元素有序序列组合,使其成为一个有序序列。
时间复杂度是O(nlogN),空间复杂度是O(n),不稳定。
代码如下:
static void Merge(int *arr,int len,int gap)//O(n)
{
int low1 = 0;
int high1 = low1+gap-1;
int low2 = high1+1;
int high2 = low2+gap<len ? low2+gap-1 : len-1;
int *brr = (int *)malloc(len*sizeof(int));
assert(brr != NULL);
int i = 0;
//归并段成对,需要归并
while(low2 < len)
{//两个归并段都还有数据
while(low1<=high1 && low2<=high2)
{
if(arr[low1] <= arr[low2])
brr[i++] = arr[low1++];
else
brr[i++] = arr[low2++];
}
//一个归并段已完成,另一个还有数据
while(low1 <= high1)
brr[i++] = arr[low1++];
while(low2 <= high2)
{
brr[i++] = arr[low2++];
}
low1 = high2+1;
high1 = low1+gap-1;
low2 = high1+1;
high2 = low2+gap<len ? low2+gap-1 : len-1;
}
//归并段不成对
while(low1 < len)
brr[i++] = arr[low1++];
for(i=0;i<len;i++)
arr[i] = brr[i];
free(brr);
}
void MergeSort(int *arr,int len)//O(nlogn),O(n),稳定
{
for(int i=1;i<len;i*=2)
Merge(arr,len,i);
}