排序算法

1.插入排序 

1.1直接插入排序一趟排序:第i趟排序,此时其0...i-1个元素时有序的,相当于把p[i]插入前0...i-1个有序序列中,形成新的有序

序列0...i。整个排序过程:对i从1...n-1重复执行上述一趟排序时间复杂度:O(n2),稳定排序

 

//straight insertion sort
void straight_insertion_sort(int p[], int n) {
    int i = 0;
    for(i = 1; i < n; ++i) {
        int tmp = p[i];
        int j = 0;
        for( j = i; j >= 1; --j) {
            if(tmp < p[j-1]) {
                p[j] = p[j-1];
            }
            else {
                break;
            }
        }
        p[j] = tmp;
    }
}

2.交换排序

2.1冒泡排序

一趟排序:第i趟,从n-1...i,比较相邻关键字,“逆序”时交换两者,一趟结束时,可以保证第i个最小

完整排序过程:i从0...n-1,重复一趟排序

时间复杂度:O(n2),稳定排序

//bubble sort
void bubble_sort(int p[], int n) {
    int i , j;
    for(i = 0; i < n; ++i) {
        for(j = n-1; j > i; --j) {
            if(p[j] < p[j-1]) {
                int tmp = p[j];
                p[j] = p[j-1];
                p[j-1] = tmp;
            } 
        }
    }
}

2.2快速排序

一趟排序:找一个关键字key,通过一趟排序将记录分成两部分,前部分关键字都小于key,后部分关键字都大于key。

完整排序过程:对前部分,后部分记录递归

时间复杂度:O(n*logn),当关键字基本有序时,退化为O(n2),不稳定排序

//quick sort
int partition(int p[], int low, int high) {
    int tmp = p[low];
    while(low < high) {
        while(low <high && p[high] > tmp)
            --high;
        if(low < high) {
            p[low] = p[high];
            ++low;
        }
        while(low <high && p[low] < tmp)
            ++low;
        if(low < high) {
            p[high] = p[low];
            --high;
        }
    }
    //printf("low=%d,high=%d,tmp=%d/n",low, high,tmp);
    //low = high + 1
    p[low] = tmp;
    
    return low;
}
void quick_sort(int p[], int low, int high) {
    if(low > high)
        return;
    
    int divide = partition(p, low, high);
    quick_sort(p, low, divide-1);
    quick_sort(p, divide+1, high);
}

3.选择排序

3.1简单选择排序

一趟排序:第i趟排序,此时0...i-1有序,i...n-1无序,从i...n-1中选择最小的一个,与p[i]交换,这样0...i有序。

完整排序过程:i从0...n-1重复进行一趟排序

时间复杂度:o(n2),稳定排序

//simple selection sort 
void simple_selection_sort(int p[], int n) {
    int i = 0;
    for(i = 0; i<n; ++i) {
        int min = p[i];
        int min_index = i;
        int j = 0;
        for(j = i; j < n; ++j) {
            if(p[j] < min) {
                min = p[j];
                min_index = j;
            } 
        }
        int tmp = p[i];
        p[i] = min;
        p[min_index] = tmp;
    }
}




 

3.2堆排序堆的性质:ri<=r2i且ri<=r2i+1(i从0...n/2),换言之就是堆顶最小(或者也可定义大顶堆)。可以将数组p[n]看做一个完全二叉树。

堆的调整:如何在输出堆顶元素后,把剩余的元素再调整成堆?(此处先不关注输出,只关注调整)此时堆顶是最小值,而堆顶元素的左子树和右子树也是堆,也就是堆顶的左孩子和右孩子中有一个是次小值。1)把堆中最后一个元素放入堆顶2)自上而下调整,左孩子、右孩子中较小的和堆顶交换做新的堆顶3)重复上述2)的调整直到叶子节点

建堆过程:从最后一个非叶子节点开始做堆调整。即n/2...0反复调整。堆排序:输出堆顶,最后一个元素和堆顶交换,做堆的调整。n...0反复调整,输出。时间复杂度:O(n*log2n),非稳定排序

//heap selection sort 
//heap adjust
void heap_adjust(int p[], int top, int n) {
    int tmp = p[top];//the top element, should be adjust
    int i = 0;
    for(i=2*top+1; i< n; i=i*2+1) {//in c language, 2i+1, 2i+2
        if(i+1 < n) {
            if(p[i+1] <= p[i]) //the smaller one 
                ++i;
        }
        if(p[i] <= tmp) {
            p[top] = p[i];
            top = i;
        }
        else {
            break;
        }
    }
    p[top] = tmp;
    
}

//heap constuct
void heap_construct(int p[], int n) {
    int m = n/2 + 1;//in c language
    int i = 0;
    for(i = m; i >=0 ; --i) {
        heap_adjust(p, i, n);
    }
}

//heap sort
void heap_sort(int p[], int n) {
    heap_construct(p, n);
    int i = 0;
    int j = 0;

    for(i = n-1; i >=0; --i ) {
        printf("%d ", p[0]);
        int tmp = p[0];
        p[0] = p[i];
        p[i] = tmp;
        heap_adjust(p,0,i);
    } 
}

 4.二路归并排序
一路归并排序:将有序序列p[start..mid]和有序序列p[mid+1...end],合并成一个有序序列p[start...end]
完整归并排序:将p从中间分开,分为两部分前部分和后部分,然后对前部分和后部分递归进行归并排序,合并。
时间复杂度:O(n*log2n),稳定排序

#define MAXNUM 10000

//merge
void merge(int p[], int start, int mid, int end) {
    int tmp1[MAXNUM], tmp2[MAXNUM];//assistant storage
    int n1, n2;
    int i=0,j=0;
    memset(tmp1, 0, sizeof(tmp1));
    memset(tmp2, 0, sizeof(tmp2));
    
    for(n1=0; n1<=mid-start; ++n1) {
        tmp1[n1] = p[start+n1];
    }
    for(n2=0; n2<=end-mid-1; ++n2) {
        tmp2[n2] = p[mid+1+n2];
    }

    n1--;//should --
    n2--;//should --

    while(i<=n1&&j<=n2) {
        if(tmp1[i] > tmp2[j]) {
            p[start++] = tmp2[j];
            ++j;
        }
        else {
            p[start++] = tmp1[i];
            ++i;
        }
    }

    if(i>n1) {
        while(j<=n2) {
            p[start++] = tmp2[j++];
        }
    }
    if(j>n2) {
        while(i<=n1) {
            p[start++] = tmp1[i++];
        }
    }

}


//merge sort
//split && merge
void split_merge(int p[], int start, int end) {
    if(start == end)
       return;
    int m = (start+end)/2;
    split_merge(p, 0, m);
    split_merge(p, m+1, end);
    merge(p, 0, m, end);
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值