归并排序 & 快速排序
归并排序
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并过程为:
比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;
否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。
归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
================
1、归并排序
-
Merge Sort
-
mergeSort.h:
-
#include <assert.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
void merge (int a[], int b[], int c[], int m, int n);
-
void mergesort (int key[], int n);
-
void wrt (int key[], int sz);
-
.
-
.
-
merge.c:
-
/* Merge a[] of size m and b[] of size n into c[]. */
-
#include "mergesort.h"
-
void merge (int a[], int b[], int c[], int m, int n)
-
{
-
int i = 0, j = 0, k = 0;
-
;
-
while (i < m && j < n)
-
if (a[i] < b[j])
-
c[k++] = a[i++];
-
else
-
c[k++] = b[j++];
-
;
-
while (i < m) /* pick up any remainder */
-
c[k++] = a[i++];
-
;
-
while (j < n)
-
c[k++] = b[j++];
-
}
-
.
-
.
-
mergesort.c:
-
/* Mergesort: Use merge() to sort an array of size n. */
-
#include "mergesort.h"
-
void mergesort (int key[], int n)
-
{
-
int j, k, m, *w;
-
for (m = 1; m < n; m *= 2)
-
; /* m is a power of 2 */
-
if (n < m) {
-
printf("ERROR: Array size not a power of 2 - bye! \n");
-
exit(1);
-
}
-
w = calloc (n, sizeof(int)); /* allocate workspace */
-
assert(w != NULL); /* check that calloc() worked */
-
for (k = 1; k < n; k *=2)
-
{
-
for (j = 0; j < n-k; j += 2*k)
-
/* Merge two subarrays of key[] into a subarray of w[]. */
-
merge(key + j, key+j+k, w+j, k, k)
-
for (j = 0; j < n; ++j)
-
key[j] = w[j]; /* write w back into key */
-
}
-
free(w); /* free the workspace */
-
}
-
.
-
.
-
main.c:
-
/* Test merge() and mergesort(). */
-
#include "mergesort.h"
-
int main(void)
-
{
-
int sz, key[] = { 4, 3, 1, 67, 55, 8, 0, 4,
-
-5, 37, 7, 4, 2, 9, 1, -1
-
};
-
sz = sizeof(key) / sizeof(int); /* the size of key[] */
-
printf("Before mergesort:\n");
-
wrt(key, sz);
-
mergesort(key, sz);
-
printf("After mergesort:\n");
-
wrt(key, sz);
-
return 0;
-
}
-
.
-
.
-
wrt.c:
-
#include "mergesort.h"
-
void wrt(int key[], int sz)
-
{
-
int i;
-
for (i = 0; i < sz; ++i)
-
printf("%4d %s", key[i], ((i < sz-1) ? " " : "\n"));
-
}
-
================
快速排序
快速排序(Quicksort)是对冒泡排序的一种改进。
基本思想:--二分查找
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

1. 设要排序的数组是A[0]……A[N-1]。首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。
2. 快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
================
2、快速排序
-
Quick Sort
-
/* Quicksort! Pointer version with macros. */
-
#define swap(x, y) {int t; t = x; x = y; y = t;}
-
#define order(x, y) if (x > y) swap(x, y)
-
#define o2(x, y) order(x, y)
-
#define o3(x, y, z) o2(x, y); o2(x, z); ow(y, z)
-
#typedef enum {yes, no} yes_no;
-
static yes_no find_pivot(int *left, int *right, int *pivot_ptr);
-
static int *partition(int *left, int *right, int pivot);
-
.
-
.
-
.//利用“递归”实现,基本思路:“分治法” quicksort(a, a+N-1);
-
void quicksort(int *left, int *right)
-
{
-
int *p, pivot;
-
if (find_pivot(left, right, &pivot) == yes) {
-
p = partition(left, right, pivot);
-
quicksort(left, p-1);
-
quicksort(p, right);
-
}
-
}
-
.
-
.
-
static yes_no find_pivot(int *left, int *right, int *pivot_ptr)
-
{
-
int a, b, c, *p;
-
a = *left; /* left value */
-
b = *(left + (right - left) / 2); /* middle value */
-
c = *right;
-
;
-
o3(a, b, c);
-
if (a < b) {
-
*pivot_ptr = b;
-
return yes;
-
}
-
if (b < c) {
-
*pivot_ptr = c;
-
return yes;
-
}
-
;
-
for (p = left+1; p <= right; ++p)
-
if (*p != *left) {
-
*pivot_ptr = (*p < *left) ? *left : *p;
-
return yes;
-
}
-
return no; /* all elements have the same value */
-
}
-
.
-
.
-
.// 主要工作由partation()函数完成
-
static int *partation(int *left, int *right, int pivot)
-
{
-
while (left <= right) {
-
while (*left < pivot)
-
++left;
-
while (*right >= pivot)
-
--right;
-
if (left < right) {
-
swap(*left, *right);
-
++left;
-
--right;
-
}
-
}
-
return left;
-
}
-
.
-
.
-
ex:
-
使用“快速”排序,高效率,复杂度:n log n
================
递归
================
PS:
[ 每日一句 ]
There’s a plan to make all of this right.
[ 每天一首英文歌 ]
" Call me maybe " - Carly Rae Jepsen
================
|-> GitHub: SpongeBob-GitHub
|--> Copyright (c) 2015 Bing Ma.