排序的稳定性
- 对于数据中相同的元素,他们在原始数据中的内容到顺序在排序后前后顺序不变
内部排序和外部排序
- 划分:是否在内存内
- 内部排序是完全在内存中进行,而外部排序有些是在内存外部进行的
排序的分类
排序的操作
直接插入排序算法
int sqlis[]={6,1,87,14,89,15,78,12,67,23};
void InsertSort(int aqlis[],int n)
{
for(int i=1;i<n;i++)
{
if(sqlis[i]>sqlis[i-1)
{
swap(sqlis[i],sqlis[i-1]);
for(int j=i-1;j>0&&sqlis[j]>sqlis[j-1];j--)
{
swap(sqlis[j],sqlis[j-1]);
}
}
}
}
折半插入排序算法
void BInsertSort(int arr[],int n)
{
for(int i=2;i<n;i++)
{
arr[0]=arr[i];
int low=1;
int high=i-1;
while(low<=high)
{
if(arr[0]>arr[mid])
low=mid+1;
else
high=mid-1;
}
}
for(int j=i;j>high+1;j--)
{
arr[j]=arr[j-1];
}
arr[high+1]=arr[0];
}
总结
- 要用0位作为记录排序的位置
- 折半插入排序必须是有序的,折半插入相当于二分法先找到,再进行插入,但是为了让数组成为有序的,在排序时,只能在查找点的位置前面,已经排好序的数据中进行使用二分法进行查找,之后再插入(通过循环,一一交换向前移动)。
- 相比于直接插入,减少了比较次数,但没有减少移动次数
2路插入排序
void TWayInsertSort(int arr[],int n)
{
int *copy;
copy[0]=arr[0];
int head,tail;
head=tail=0;
for(int i=1;i<n;i++)
{
if(arr[i]<copy[head])
{
head=(head-1+n)%n;
copy[head]=arr[i];
}
else if(arr[i]>copy[tail])
{
tail++;
copy[tail]=arr[i];
}
else
{
tail++;
copy[tail]=copy[tail-1];
for(int j=tail-1;arr[i]<copy[(j-1+n)%n];j=(j-1+n)%n;)
{
copy[j]=copy[(j-1+n)%n];
}
copy[j]=arr[i];
}
}
for(int i=0;i<n;i++)
{
arr[i]=copy[head];
head=(head+1)%n;
}
}
总结
- 此方法没有使用哨兵位
- 注意新建数组是循环的,因此-1时要(i-1+n)%n,+1时要(i+1)%n,在最后为原数组重新赋值时必须从拷贝数组的头部开始赋值
- 减少了移动次数
表插入排序
#define MAXVALUE 0x7FFFFFFF
typedef struct SLnode
{
int data;
int link;
}Slnode;
typedef SLnode Table[10];
void main()
{
int arr[]={0,24,64,84,12,53,43,46,14};
int n=9;
Table tb;
tb[0].data=MAXVALUE;
tb[0].link=0;
for(int i=1;i<n;i++)
{
tb[i].data=arr[i];
tb[i].link=0;
}
TableInsertSort(arr,n);
}
void TableInsertSort(int arr[],int n)
{
arr[0].link=1;
int p,q;
for(int i=2;i<n;i++)
{
p=arr[0].link;
q=0;
while(p!=0&&arr[p].data<=arr[i].data)
{
q=p;
p=t[p].link;
}
arr[i].link=arr[q].link;
arr[q].link=i;
}
}
总结
- 用0位置表示最小值,只记录了最小值的位置
- 开始时需要将0位初始化
- 与直接插入相比,只是把移动改成了修改2n次指针值,但是比较次数并未改变,时间复杂度仍为n^2
- 最终形成了有序链表,不能进行顺序查找,只能按照链表方式进行查找
插入排序之希尔排序
int dlta[]={5,3,2,1};
int t=sizeof(dlta)/sizeof(int);
void ShellSort(int arr[],int n,int dlta[],int t);
void ShellInsert(int arr[],int n,int dk)
{
for(int i=dk+1;i<n;i++)
{
if(arr[i-dk]>arr[i])
{
int j;
arr[0]=arr[i];
for(j=i-dk;j>0&&arr[0]<arr[j];j-=dk)
{
arr[j+dk]=arr[j];
}
arr[j]=arr[0];
}
}
}
void ShellSort(int arr[],int n,int dlta[],int t)
{
for(int k=0;k<t;k++)
{
ShellInsert(arr,n,dlta[k]);
}
}
总结
- 希尔排序让其基本有序,效率较高
- 但仍未得到一些较好的增量序列