排序算法基本知识点
数据结构:从操作角度,排序是线性结构的一种操作,待排序记录可以用顺序存储结构或链接存储结构。
排序算法的稳定性:具有相同值的记录,在排序后,相对顺序如果没有发生变化称排序算法稳定,反之,则称为不稳定。
排序的分类:内排序:在排序的整个过程中,待排序的所有记录全部被放置在内存中。
外排序:由于待排序记录太多,不能同时放置在内存,而需要将一部分放置在内存中,另一部分记录放置在外存中, 整个排序过程需要在内外存之间多次交换数据才能得到排序的结果。
排序算法的两种基本操作:比较和移动
性能评估:时间开销和辅助存储空间
插入排序
直接插入排序
基本思想:依次将待排序序列的每一个记录插入到一个已经排好序的序列中,直到所有记录全都排好。
理解起来就是:起初已排序序列为空,你从未排序的麻袋里拿一个数,就可以直接放入已排序麻袋,而第二数拿出来之后,就不能直接扔在已排序麻袋中了,要比较一下,如果比麻袋中的那个数小,就排在他的前面,反之,放在他的后面,对于第三个数,他就遍历已排序麻袋,找到合适他的位置。
说明:插入排序在原数组中原地排序,故空留索引0处做每次记录的暂存。
public int[] insertSort(int []nums)
{
int temp;
for(int i=1;i<nums.length;i++)//从未排序序列中取记录
{
temp=nums[i];
int j=i-1;
for(;temp<nums[j];j--)//在已排序中找位置
{
nums[j+1]=nums[j];
}
nums[j+1]=temp;
}
return nums;
}
性能评估:
最好情况:待排序序列为正序,那么每个记录只要与与已排序序列的最后一个比较,然后temp再次赋值给nums[i],比较次数n-1,移动次数2(n-1),时间复杂度为O(n)
最坏情况:待排序序列为反序,那么第i个记录要与与已排序序列比较(i-1)次,每次比较已排序序列中的一条记录就要向后移动一次,移动次数(i-1),总比较次数:(1+2+..+n-1)=n(n-1)/2;移动次数:每次除比较移动外,还有赋值temp和temp赋值给数组(3+4+...+n+1)=(n+4)(n-1)/2时间复杂度为O(n^2).
希尔排序
基本思想:先将整个待排序记录分割成若干个子序列,在子子序列内分别进行直接插入排序,待整个序列基本有序时,再对全体记录进行一次直接插入排序。
分段规则:d=nums.length/2;并依次处以2缩小,当d=1时,就是对整个序列直接插入排序
public int[] shellSort(int []nums)
{
for(int d=nums.length/2;d>=1;d=d/2)
{
for(int i=d+1;i<nums.length;i++)
{
int temp=nums[i];
int j=i-d;
for(;j>=0&&nums[j]>temp;j=j-d){
nums[j+d]=nums[j];
}
nums[j+d]=temp;
}
}
return nums;
}
时间性能在:O(n^2)和O(nlog2n)之间
交换排序
起泡排序
基本思想:两两比较相邻记录的关键码,反序则交换,反之,继续。
它每一趟走下来,都可以把未排好序列中最大的换到最后。
改进:设置变量exchange记载每次记录交换的位置,则一趟排序后,exchange记载的一定时这趟排序中记录的最后一次交换的位置,从此位置之后的所有记录均已经有序。
public int[]bubbleSort(int []nums)
{
int temp;
int exchange=nums.length-1;
int bound;
while(exchange!=0)
{
bound=exchange;
exchange=0;
for(int i=0;i<bound;i++)
{
if(nums[i]>nums[i+1])
{
temp=nums[i];
nums[i]=nums[i+1];
nums[i+1]=temp;
exchange=i;
}
System.out.println(exchange);
}
}
return nums;
}
时间复杂度:O(n^2);
快速排序
在起泡排序中,记录的比较和移动是在相邻位置进行的,记录每次只能前移或后移一个位置。
public int[]quickSort(int []nums,int start,int end)
{
int p=0;
if(start<end)
{
p=partition(nums,start,end);
nums=quickSort(nums, start, p-1);
nums=quickSort(nums, p+1, end);
}
return nums;
}
public int partition(int nums[],int start,int end)
{
int temp;
while(start<end)
{
while(start<end&&nums[start]<nums[end])
end--;
if(start<end)
{
temp=nums[start];
nums[start]=nums[end];
nums[end]=temp;
start++;
}
while(start<end&&nums[start]<=nums[end])
start++;
if(start<end)
{
temp=nums[start];
nums[start]=nums[end];
nums[end]=temp;
end--;
}
}
return start;
}