内排序算法
每次需要排序的时候总是会忘记基本的排序算法,为了防止自己再次忘记,写个博客加深自己的印象:
简单选择排序
简单选择排序大概就是最简单我们最容易想到的一种排序方法,一共进行n-1次选择,在第i次选择中选择第i小的数放在相应的位置。我们可以想象一种场景,有一些账单需要我们按照时间进行排序,我妈每次选择最早的一张拿在手上,再从剩下的账单里选择最早的放在手中账单的底下。
static class SelectSort{
static void select_sort(int[] array){
for(int i=0;i<array.length;i++){
int min=i;
for(int j=i+1;j<array.length;j++){
if(array[min]>array[j]){
min=j;
}
}
if(min!=i){
exchange(array,min,i);//交换min和i
}
}
}
}
每次选择出一个第i小的数放在正确的位置会发生交换,导致元素位置改变,所以是不稳定的。
插入排序
插入排序我们可以想象我们在玩扑克牌,每次从牌堆中拿一张,根据牌面的大小插入手中的牌。
static class InsertionSort{
static void insertion_sort(int[] array){
for(int j=1;j<array.length;j++){
int key=array[j];
int i=j-1;
while(i>=0&&array[i]>key){
array[i+1]=array[i];
i--;
}
array[i+1]=key;
}
}
}
快速排序
快速排序的重点就在划分,我们选择一个标准元素,然后让它左边的元素都小于它,右边的元素都大于它。接着进行递归处理它左边的所有元素和右边的所有元素。
static class QuickSort{
static void quick_sort(int[] array,int p,int q){
if(p<q){
int r=partition(array,p,q);
quick_sort(array,p,r-1);
quick_sort(array,r+1,q);
}
}
static int partition(int[] array,int p,int q){
int key=array[q];
int i=p-1;
for(int j=p;j<q;j++){
if(array[j]<key){
i++;
exchange(array,i,j);//交换元素i和j
}
}
exchange(array,++i,q);//交换元素i+1和q
return i;
}
}
在划分的过程中存在交换,因此会打乱相同元素相对顺序。
冒泡排序
每次比较相邻的元素,如果左边的元素比右边的元素大,那么就会交换位置,所以每一轮排序都会把最大的数放在正确的位置。
static class BubbleSort{
static void bubble_sort(int[] array){
for(int i=0;i<array.length-1;i++){
for(int j=0;j<array.length-i-1;j++){
if(array[j]>array[j+1]){
exchange(array,j,j+1);//交换j和j+1的位置
}
}
}
}
}
归并排序
开始将数组分为长度为1的n个有序表,然后逐步合并。
static class MergeSort{
static void merge_sort(int[] array,int[] array1){
int h=1;
while(h<array.length){
merge_pass(array,array1,h);
h=2*h;
for(int i=0;i<array.length;i++){
array[i]=array1[i];
}
}
}
static void merge_pass(int[] array,int[] array1,int h){
int i=0;
while(i<array.length-2*h+1){
merge(array,array1,i,i+h-1,i+2*h-1);
i+=2*h;
}
if(i<array.length-h+1){
merge(array,array1,i,i+h-1,array.length-1);
}else{
for(;i<array.length;i++){
array1[i]=array[i];
}
}
}
static void merge(int[] array,int[] array1,int a,int b,int c){
int i=a;
int j=b+1;
int k=a;
while(i<=b&&j<=c){
if(array[i]<array[j]){
array1[k++]=array[i++];
}else{
array1[k++]=array[j++];
}
}
while(i<=b)array1[k++]=array[i++];
while(j<=c)array1[k++]=array[j++];
}
}
希尔排序
对直接插入排序的一种改进,因为基本有序的序列,直接插入最快,记录数很少的无序序列插入也很快。将待排序的记录集分成多个子集,分别对这些子集进行插入排序。
static class ShellSort{
static void shell_sort(int[] array){
for(int d=array.length/2;d>=1;d=d/2){
for(int i=d;i<array.length;i++){
if(array[i]<array[i-d]){
int key=array[i];
int j=i-d;
for(;j>=0&&key<array[j];j=j-d){
array[j+d]=array[j];
}
array[j+d]=key;
}
}
}
}
}
堆排序
觉得百度百科写得很清楚了
堆排序
几种排序算法的比较
算法名称 | 稳定性 | 算法复杂度 |
---|---|---|
简单选择排序 | 不稳定 | O(N^2) |
插入排序 | 稳定 | 最坏情况下O(N^2) |
快速排序 | 不稳定 | 平均情况O(N*log2(N)),最坏情况O(N^2) |
希尔排序 | 不稳定 | O(N*log2(N))到O(N^2) |
冒泡排序 | 稳定 | 最坏情况O(N^2) |
归并排序 | 稳定 | O(N*log2(N)) |
稳定性是指在排序完成之后相同值的元素的相对位置不会改变*