一些常见的排序方法

插入排序: 时间复杂度O(n^2), 辅助存储空间O(1), 稳定排序

插入排序
#include <stdio.h>
#include <stdlib.h>

int A[10000];

void insertsort(int a[], int p, int r) {
    int i, j; 
    for (i = 2; i <= r; ++i) {
        a[0] = a[i]; // 作为元素的备份和起到监视哨的作用 
        for (j = i-1; a[0] < a[j]; --j) { 
            a[j+1] = a[j];
        }
        a[j+1] = a[0];
    }
}

int main() {
    int N;
    while (1) {
        printf("请输入要排序的元素个数:");
        scanf("%d", &N); 
        for (int i = 1; i <= N; ++i) {
            scanf("%d", &A[i]);
        }
        insertsort(A, 1, N);
        for (int i = 1; i <= N; ++i) {
            printf("%d ", A[i]);    
        }
        puts("");
    }
}

 

 

快速排序: 时间复杂度O(nlogn), 辅助存储空间O(logn), 非稳定排序

快速排序
#include <stdio.h>
#include <stdlib.h>

int A[10000]; 

int patition(int a[], int p, int r) {
    int i = p-1;
    for (int j = p; j <= r-1; ++j) {
        if (a[j] < a[r]) {
            ++i;
            int t = a[i];
            a[i] = a[j];
            a[j] = t;
        }
    }
    int t = a[i+1];
    a[i+1] = a[r];
    a[r] = t;
    return i+1;
} 

void quicksort(int a[], int p, int r) {
    if (p < r) {
        int q = patition(a, p, r);
        quicksort(a, p, q-1);
        quicksort(a, q+1, r);
    }
}

int main() {
    int N;
    while (1) {
        printf("请输入要排序的元素个数:");
        scanf("%d", &N); 
        for (int i = 1; i <= N; ++i) {
            scanf("%d", &A[i]);
        }
        quicksort(A, 1, N);
        for (int i = 1; i <= N; ++i) {
            printf("%d ", A[i]);    
        }
        puts("");
    }
    return 0;    
}

 

 

树形选择排序: 时间复杂度O(nlogn), 辅助存储空间O(n), 稳定排序

树形选择排序
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define INF 0x3f3f3f3f

int N, seq[5000];

int min(int x, int y) {
    return x < y ? x : y;
}

int modify(int x) {
    int lch = x<<1, rch = x<<1|1;
    if (seq[lch] == INF && seq[rch] == INF) {
        return seq[x] = INF; // 下面已经没有了节点
    }
    if (seq[lch] == seq[x]) { // 如果已经输出的节点来自左边的子树
        seq[x] = min(modify(lch), seq[rch]);
    } else {
        seq[x] = min(modify(rch), seq[lch]);
    }
    return seq[x];
}

int main() {
    while (1) {
        memset(seq, 0x3f, sizeof (seq));
        printf("请输入要排序的元素个数:");
        scanf("%d", &N);
        printf("请输入%d个元素,以空格隔开:\n", N);
        int deep = int (ceil(log2(1.*N))); // deep 表示要到达第deep+1层,才可以容纳下N个元素
        int sta = int (pow(2, deep));
        for (int i = sta, j = 0; j < N; ++i, ++j) {
            scanf("%d", &seq[i]);
        }
        for (int i = sta-1; i >= 1; --i) {
            int lch = i<<1, rch = i<<1|1; // 相当于 lch = i*2, rch = i*2+1 
            seq[i] = min(seq[lch], seq[rch]);
        }
        while (seq[1] != INF) {
            printf("%d ", seq[1]);
            seq[1] = modify(1);
        }
        puts("");
    }
    return 0;    
}

 

 

堆排序: 时间复杂度O(nlogn), 辅助存储空间O(1), 非稳定排序

堆排序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

int N, seq[5000];

void swap(int a, int b) {
    int t = seq[a];
    seq[a] = seq[b];
    seq[b] = t;    
}

void down(int p) { // down操作是用来完成使得以节点p为根的子树保持堆的性质 
    int lch = p<<1, rch = p<<1|1;
    if (lch <= N && seq[p] > seq[lch]) {
        swap(p, lch);
        down(lch);
    }
    if (rch <= N && seq[p] > seq[rch]) {
        swap(p, rch);
        down(rch);
    }
}

void build() {
    for (int i = N/2; i >= 1; --i) {
        int lch = i<<1, rch = i<<1|1;
        if (lch <= N && seq[i] > seq[lch]) {
            swap(i, lch);
            down(lch);
        }
        if (rch <= N && seq[i] > seq[rch]) {
            swap(i, rch);
            down(rch);
        }
    }
}

int main() { 
    while (1) {
        printf("请输入要排序的元素个数:");
        scanf("%d", &N);
        printf("请输入%d个元素,以空格隔开:\n", N);
        for (int i = 1; i <= N; ++i) {
            scanf("%d", seq+i);    
        }
        build();
        while(N) {
            printf("%d ", seq[1]); 
            swap(1, N--); // 将第一个元素与最后一个元素交换,元素个数减1
            down(1);
        }
        puts("");
    }
    return 0;    
}

 

 

归并排序: 时间复杂度O(nlogn), 辅助存储空间O(n), 稳定排序

归并排序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

int N, seq[5000], temp[5000];

void Merge_Sort(int l, int r) {
    if (l >= r) return; // 如果只有一个元素或者没有元素 
    int mid = (l + r) >> 1; // 右移一位相当 (l + r) / 2
    Merge_Sort(l, mid); // 对两个部分进行一个排序 
    Merge_Sort(mid+1, r);
    // 下面的合并操作一般来说是分治方法里面的难点
    int k = 0, i = l, j = mid+1; 
    // k表示将要合并到的数组的下标, i表示左半部分下标, j表示右半部分下标
    while (i <= mid && j <= r) {
        if (seq[i] < seq[j]) {
            temp[k++] = seq[i++];    
        } else {
            temp[k++] = seq[j++];    
        }
    }
    while (i <= mid) temp[k++] = seq[i++];
    while (j <= r) temp[k++] = seq[j++];
    for (i = 0; i < k; ++i) {
        seq[l + i] = temp[i];
    }
}

int main() {
    while (1) {
        memset(seq, 0x3f, sizeof (seq));
        printf("请输入要排序的元素个数:");
        scanf("%d", &N);
        printf("请输入%d个元素,以空格隔开:\n", N);
        for (int i = 1; i <= N; ++i) {
            scanf("%d", seq+i);    
        }
        Merge_Sort(1, N);
        for (int i = 1; i <= N; ++i) {
            printf("%d ", seq[i]);
        }
    }
    return 0;    
}

 

当然还有冒泡和选择许多... 就写这么几种,够用了.  到最后还是调用的库函数sort.

posted @ 2013-01-13 14:27  沐阳  阅读(317)  评论(0编辑  收藏  举报