一、排序的概念
1.概念:排序就是使一串记录,按照其中某些关键字的大小,递增或递减的排列起来的操作
稳定性:假定在待排序和记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,则称这种排序算法是稳定的,否则称为不稳定的。
内部排序:数据元素全部放在内存中的排序
外部元素:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序
2.常见的排序算法
-
插入排序
直接插入排序
希尔排序 -
选择排序
选择排序
堆排序 -
交换排序
冒泡排序
快速排序 -
归并排序
二、算法的实现
1.插入排序
- 直接插入排序
思想:把待排序的记录按其关键码值的大小逐个插入到一个已经排列好的有序序列中,直到所有的记录插完为止,得到一个新的有序序列
void insert_sort(int a[],int len)
{
int i,j;
for(i=1;i<len;++i)
{
for(j=i-1;j>=0;--j)
{
if(a[i]<a[j])
{
int tmp=a[i];
a[i]=a[j];
a[j]=tmp;
i=j;
}
}
}
}
特性:
元素集合越接近有序,直接插入排序算法时间效率越高
时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:稳定
- 希尔排序
又称缩小增量法,基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离相同的记录分为一个组,并对每一组内的记录进行排序。然后重复上述分组和排序工作。当间隔为1时,所有记录在统一组内排好序
void shell_sort(int a[],int len)
{
int gap=len;
while(1)
{
gap=gap/2;
for(int i=0;i<len;++i)
{
for(int j=i+gap;j<len;j+=gap)
{
if(a[i]>a[j])
{
int tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
}
}
if(gap==1)
break;
}
特性:
希尔排序是对直接插入排序的优化
当gap>1时都是预排序,目的是让数组更接近有序,当gap==1时,数组已经是接近有序的了
平均时间复杂度:O(N^1.3 - N^2)
稳定性:不稳定
2.选择排序
- 直接选择排序
思想:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完
void select_sort(int a[],int len)
{
for(int i=0;i<len;++i)
{
int min=i;
for(int j=i+1;j<len;++j)
{
if(a[j]<a[min])
min=j;
}
int tmp=a[i];
a[i]=a[min];
a[min]=tmp;
}
}
特性:
时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:不稳定
- 堆排序
堆排序是指利用堆这种数据结构所设计的一种排序算法,它是选择排序的一种。通过堆来进行选择数据,需注意的是排升序要建大堆,排降序要建小堆
void Swap(int a[],int i,int j)
{
int tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
void adjust(int a[],int i,int len)
{
int tmp=a[i];
for(int k=2*i+1;k<len;k=2*k+1)
{
if(k+1<len&&a[k]<a[k+1]
k=k+1;
if(a[k]>tmp)
{
a[i]=a[k];
i=k;
}
else
{
break;
}
}
a[i]=tmp;
}
void Heap_sort(int a[],int len)
{
int i=len/2-1;
for(i;i>=0;--i)
{
adjust(a,i,len);
}
for(j=i-1;j>=0;--j)
{
Swap(a,0,j);
adjust(a,0,j);
}
}
特性:
时间复杂度:O(N*logN)
空间复杂度:O(1)
稳定性:不稳定