1. 程式人生 > >插入排序與歸併排序及優化

插入排序與歸併排序及優化

看CLRS順便做下筆記總結一下,理清思路。(所有排序例子皆為從小到大,各位覺得哪裡能更好地改進都可以指出來)

插入排序(c語言實現)

最壞情況下的執行時間是Θ(n*n),跟氣泡排序,選擇排序的最壞情況下的執行時間是相同的

但是,運算的速度 插入>選擇(相比冒泡交換的次數較少)>冒泡

最簡單的例子啦,打牌的時候一張一張的拿到手裡插入排序。

上程式碼

#include<stdio.h>
#include<stdlib.h>
int main(void){
    int j,i,num,key;
    scanf("%d",&num);
    int
*ptr; ptr=(int *)malloc(num*sizeof(int));//動態記憶體分配 for(i=0;i<num;i++){ scanf("%d",&ptr[i]); } for(i=1;i<num;i++){ key=ptr[i];//你拿到的“牌” j=i-1;//通過迭代找到合適的位置,將其他牌向前推 while(j>=0&&ptr[j]>key){ ptr[j+1]=ptr[j]; j-=1; } ptr[j+1
]=key;//最後把牌放進去 } for(i=0;i<num;i++){ printf("%d ",ptr[i]); } free(ptr); return 0; }

以上的方法是從迭代實現插入排序

那麼我們試下遞迴實現插入排序

#include<stdio.h>
#include<stdlib.h>
void insert_sort(int *ptr,int num);
int main(void){
    int i,num,*ptr;
    scanf("%d",&num);
    ptr=(int
*)malloc(num*sizeof(int)); for(i=0;i<num;i++){ scanf("%d",&ptr[i]); } insert_sort(ptr,num-1); for(i=0;i<num;i++){ printf("%d ",ptr[i]); } free(ptr); return 0; } void insert_sort(int *ptr,int num){ int j,i,key; static index=0; j=index+1; key=ptr[j]; i=j-1; while(i>=0&&ptr[i]>key){ ptr[i+1]=ptr[i]; i--; } ptr[i+1]=key; index++; if(index<num){ insert_sort(ptr,num); } }

歸併排序(c語言實現)

採用的是分治的思想Divide and Conquer

最壞情況下的執行時間是Θ(n*Ign),其中Ign相比任何的線性函式增長慢,所以歸併排序的效能要優於插入排序。

歸併排序就等於畫樹,其中樹的每一層加起來都等於cn,樹的高度一共是Ign層,merge的子程式耗費的時間是Θ(n)

一共加起來的時間就是cn*lgn+Θ(n),通過漸近符號得到最高項就是Θ(n*Ign)

上程式碼(這裡的歸併排序並沒有採用哨兵的方法)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void merge_sort(int *ptr,int low,int high);
void merge(int *ptr,int leftlow,int lefthigh,int rightlow,int righthigh);
int main(void){
    int size,index;
    scanf("%d",&size);
    int *ptr;
    ptr=(int *)malloc(size*sizeof(int));
    for(index=0;index<size;index++){
        scanf("%d",&ptr[index]);
    }
    merge_sort(ptr,0,size-1);
    for(index=0;index<size;index++){
        printf("%d ",ptr[index]);
    }
    free(ptr);
    return 0;
}


void merge_sort(int *ptr,int low,int high){
    if(low<high){
        int middle;
        middle=low+(high-low)/2;
        merge_sort(ptr,low,middle);
        merge_sort(ptr,middle+1,high);
        merge(ptr,low,middle,middle+1,high);
    }
}


void merge(int *ptr,int leftlow,int lefthigh,int rightlow,int righthigh){
    int num;
    num=(lefthigh-leftlow+1)+(righthigh-rightlow+1);
    int *sort_array;
    int index=0;
    int leftindex=leftlow;
    int rightindex=rightlow;
    sort_array=(int *)malloc(num*sizeof(int));
    while(leftindex<=lefthigh&&rightindex<=righthigh){
        if(ptr[leftindex]<=ptr[rightindex]){
            sort_array[index++]=ptr[leftindex++];
        }
        else{
            sort_array[index++]=ptr[rightindex++];
        }
    }
    while(leftindex<=lefthigh){
        sort_array[index++]=ptr[leftindex++];
    }
    while(rightindex<=righthigh){
        sort_array[index++]=ptr[rightindex++];
    }
    memcpy(ptr+leftlow,sort_array,num*sizeof(int));
    free(sort_array);
}

那麼,就如函式y=n*n與函式y’=n*n*n一樣存在一個點,使得小於該點時y

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 30
void merge_sort(int *,int ,int );
void merge(int *,int ,int ,int ,int );
void insert_sort(int *,int ,int );
int main(void){
    int i,size,*ptr;
    scanf("%d",&size);
    ptr=(int *)malloc(size*sizeof(int));
    for(i=0;i<size;i++){
        scanf("%d",&ptr[i]);
    }
    merge_sort(ptr,0,size-1);
    for(i=0;i<size;i++){
        printf("%d ",ptr[i]);
    }
    free(ptr);
    return 0;
}


void merge_sort(int *ptr,int low,int high){
    if((high-low)<=MAX){
        insert_sort(ptr,low,high);
    }
    else if((high-low)>MAX){
        int mid;
        mid=low+(high-low)/2;
        merge_sort(ptr,low,mid);
        merge_sort(ptr,mid+1,high);
        merge(ptr,low,mid,mid+1,high);
    }
}


void insert_sort(int *ptr,int low,int high){
    int i,j;
    int key;
    for(j=low+1;j<=high;j++){
        key=ptr[j];
        i=j-1;
        while(i>=low&&ptr[i]>key){
            ptr[i+1]=ptr[i];
            i--;
        }
        ptr[i+1]=key;
    }
}


void merge(int *ptr,int leftlow,int lefthigh,int rightlow,int righthigh){
    int size;
    size=(lefthigh-leftlow)+1+(righthigh-rightlow)+1;
    int *sort_array;
    sort_array=(int *)malloc(size*sizeof(int));
    int index=0;
    int leftindex=leftlow;
    int rightindex=rightlow;
    while(leftindex<=lefthigh&&rightindex<=righthigh){
        if(ptr[leftindex]<ptr[rightindex]){
            sort_array[index++]=ptr[leftindex++];
        }
        else{
            sort_array[index++]=ptr[rightindex++];
        }
    }
    while(leftindex<=lefthigh){
        sort_array[index++]=ptr[leftindex++];
    }
    while(rightindex<=righthigh){
        sort_array[index++]=ptr[rightindex++];
    }
    memcpy(ptr+leftlow,sort_array,size*sizeof(int));
    free(sort_array);
}