您的位置:首页 > 编程语言 > C语言/C++

C语言:排序算法

2015-09-28 10:46 375 查看
本节中所讲的排序均以升序为例。

一、冒泡排序

1. 基本思想:

从左到右,两两比较;如果发现前者比后者大,则交换元素。每一轮比较完毕后,序列中最大的一个元素会至于最后。流程图如下:



2. 代码清单:

void bubbleSort(int *a, int length) {
    int i,j;
    for (i = length - 1; i >= 0; i--) {
        for (j = 0; j < i; j++) {
            if (a[j] > a[j + 1]) {
                int temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }
}

int main(int argc, const char * argv[]) {
    
    int a[] = {2, 4, 9, 1, 0, 3};
    bubbleSort(a, 6);
    
    for (int i = 0; i < 6; i++) {
        printf("%d\n", a[i]);
    }
    
    return 0;
}


二、选择排序

1. 基本思想:

每次循环的时候,找出数组中最小的元素,并且与循环操作中数组最前面的元素进行交换。流程图如下:



2. 代码清单:

void selectionSort(int *a, int length) {
    int outer, inner, min;
    for (outer = 0; outer < length - 1; outer++) {
        min = outer;
        for (inner = outer + 1; inner < length; inner++) {
            if (a[inner] < a[min]) {
                min = inner;
            }
        }
        
        int temp = a[outer];
        a[outer] = a[min];
        a[min] = temp;
    }
}

int main(int argc, const char * argv[]) {
    
    int a[] = {2, 4, 9, 1, 0, 3};
    selectionSort(a, 6);
    
    for (int i = 0; i < 6; i++) {
        printf("%d\n", a[i]);
    }
    
    return 0;
}


三、插入排序

1. 基本思想:

每次假定数组第一个元素为在正确的位置上面,然后在数组后面依次寻找比这个元素大得并且是最小的那个元素,将其插入到指定元素的后面,与此同时,那些原本紧挨着指定元素后面的所有元素,依次往后移动一个位置。



2. 代码清单:

void insertSort(int *a, int length) {
    int i, j, target;
    // 假定第一个元素被放到了正确的位置上,这样仅需要便利n-1次
    for (i = 1; i < length; i++) {
        j = i;
        target = a[i];
        while (j > 0 && target < a[j - 1]) {
            a[j] = a[j - 1];
            j--;
        }
        
        a[j] = target;
    }
}

int main(int argc, const char * argv[]) {
    
    int a[] = {4, 2, 6, 1, 8, 3};
    insertSort(a, 6);
    for (int i = 0; i < 6; i++) {
        printf("%d\t", a[i]);
    }
    
    return 0;
}


四、归并排序

1. 基本思想:

将一个数组分解成多个数组,依次对每个子数组进行排序,最终将排序完成的子数组合并,进行最终的排序。



2. 代码清单:

void merge(int a[], int p, int q, int r) {
    int i, j, k, n1, n2;
    // 变量用于申请两个内存空间
    int *front, *back;
    // 前一部分长度
    n1 = q - p + 1;
    // 后一部分长度
    n2 = r - q;
    // 申请两个空间存放拍好的数组
    front = (int *)malloc(n1 * sizeof(int));
    back = (int *)malloc(n2 * sizeof(int));
    // 将数组转入两个新空间中
    for (int i = 0; i < n1; i++) {
        front[i] = a[p + i];
    }
    for (int i = 0; i < n2; i++) {
        back[i] = a[q + i + 1];
    }
    
    // 将元素合并
    i = 0; j = 0; k = p;
    while (i < n1 && j < n2) {
        if (front[i] < back[j]) {
            a[k++] = front[i++];
        } else {
            a[k++] = back[j++];
        }
    }
    
    // 将剩余元素合并
    while (i < n1) {
        a[k++] = front[i++];
    }
    while (j < n2) {
        a[k++] = back[j++];
    }
}

void marge_sort(int a[], int p, int r) {
    int q;
    if (p < r) {
        q = (p + r) / 2;
        marge_sort(a, p, q);
        marge_sort(a, q + 1, r);
        merge(a, p, q, r);
    }
}

int main(int argc, const char * argv[]) {
    
    int a[8] = {1, 6, 4, 5, 3, 9, 7, 8};
    
    marge_sort(a, 0, 7);
    
    for (int i = 0; i < 8; i++) {
        printf("%d\t", a[i]);
    }
    
    return 0;
}


五、快速排序

1. 基本思想:

假设用户输入了如下数组:
下标
0
1
2
3
4
5
数据
6
2
7
3
8
9
创建变量i=0(指向第一个数据), j=5(指向最后一个数据), k=6(赋值为第一个数据的值)。

我们要把所有比k小的数移动到k的左面,所以我们可以开始寻找比6小的数,从j开始,从右往左找,不断递减变量j的值,我们找到第一个下标3的数据比6小,于是把数据3移到下标0的位置,把下标0的数据6移到下标3,完成第一次比较:
下标
0
1
2
34
5
数据
3
2
7
6
8
9
i=0 j=3 k=6

接着,开始第二次比较,这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2的数据是第一个比k大的,于是用下标2的数据7和j指向的下标3的数据的6做交换,数据状态变成下表:
下标
0
1
2
3
4
5
数据
3
2
6
7
8
9
i=2 j=3 k=6

称上面两次比较为一个循环。

接着,再递减变量j,不断重复进行上面的循环比较。

在本例中,我们进行一次循环,就发现i和j“碰头”了:他们都指向了下标2。于是,第一遍比较结束。得到结果如下,凡是k(=6)左边的数都比它小,凡是k右边的数都比它大:
下标
0
1
2
3
4
5
数据
3
2
6
7
8
9
如果i和j没有碰头的话,就递加i找大的,还没有,就再递减j找小的,如此反复,不断循环。注意判断和寻找是同时进行的。

然后,对k两边的数据,再分组分别进行上述的过程,直到不能再分组为止。
2. 代码清单:
void sort(int *a, int left, int right) {
    // 表示一组排序结束
    if (left > right) {
        return;
    }
    int i = left; int j = right; int key = a[left];
    while (i < j) {
        // 找到比key小的值,交换位置(放在左边)
        while (i < j && key <= a[j]) {
            j--;
        }
        a[i] = a[j];
        
        // 找到比key大的值,交换位置(放在右边)
        while (i < j && key >= a[i]) {
            i++;
        }
        a[j] = a[i];
    }
    
    a[i] = key;
    // 递归执行
    sort(a, left, i - 1);
    sort(a, i + 1, right);
}

int main(int argc, const char * argv[]) {
    
    int a[] = {3, 5, 8, 1, 0, 2};
    sort(a, 0, 5);
    for (int i = 0; i < 6; i++) {
        printf("%d\t", a[i]);
    }
    
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: