排序算法要点及其C语言实现
2014-09-01 11:16
459 查看
1. 快速排序:
不稳定排序,原址排序最好情况复杂度:O(nlgn)
最坏情况复杂度:O(n^2),当输入数组已经排好序时(包括所有元素都一样时)。
#include <stdio.h> #include <stdlib.h> #include <time.h> void PrintArrays(const int* a, const int num_elements) { for (int i = 0; i < num_elements; ++i) { printf("%d\t", a[i]); } printf("\n"); } void Swap(int* a, int* b) { const int temp = *a; *a = *b; *b = temp; } int RandomInRange(const int min, const int max) { srand(time(NULL)); const int index = rand() % (max - min + 1) + min; return index; } int Partition(int* a, const int length, const int first, const int last) { if (a == NULL || length <= 0 || first < 0 || last >= length) { fprintf(stderr, "Invalid Parameters"); exit(EXIT_FAILURE); } const int index = RandomInRange(first, last); Swap(&a[index], &a[last]); int i = first - 1; for (int j = first; j < last; ++j) { if (a[j] <= a[last]) { ++i; if (i != j) Swap(&a[i], &a[j]); } } ++i; Swap(&a[i], &a[last]); return i; } void QuickSort(int* a, const int length, const int first, const int last) { if (first < last) { const int index = Partition(a, length, first, last); QuickSort(a, length, first, index - 1); QuickSort(a, length, index + 1, last); } } int main(int argc, char** argv) { int a[8] = { 11, 10, 13, 5, 8, 3, 2, 8 }; printf("Before Sorting: \n"); PrintArrays(a, 8); QuickSort(a, 8, 0, 7); printf("After Sorting : \n"); PrintArrays(a, 8); return 0; }
2.归并排序:
稳定排序,非原址排序最好情况复杂度:O(nlgn)
最坏情况复杂度:O(nlgn)
缺点:需要额外内存空间O(n)
#include <stdio.h> #include <stdlib.h> #include <limits.h> void PrintArrays(const int* a, const int num_elements) { for (int i = 0; i < num_elements; ++i) { printf("%d\t", a[i]); } printf("\n"); } void Merge(int* a, int* aux, const int first, const int middle, const int last) { if (a == NULL || aux == NULL) { fprintf(stderr, "Invalid Parameters!\n"); exit(EXIT_FAILURE); } const int n1 = middle - first + 1; const int n2 = last - middle; for (int i = 0; i < n1; ++i) //将子数组a[first...middle]拷贝到辅助数组aux前半部分 { aux[i] = a[first + i]; } for (int j = 0; j < n2; ++j) //将子数组a[middle+1...last]拷贝到辅助数组aux后半部分 { aux[n1 + 1 + j] = a[middle + 1 + j]; } aux[n1] = INT_MAX; // 保存哨兵值 aux[n1 + n2 + 1] = INT_MAX; // 保存哨兵值 int i = 0; int j = n1 + 1; int k; for (k = first; k < last; ++k) //将数组元素值两两比较,并合并到原数组a { if (aux[i] <= aux[j]) a[k] = aux[i++]; else a[k] = aux[j++]; } for (; i < n1; ++i) a[k++] = aux[i]; for (; j < n2; ++j) a[k++] = aux[j]; } void MergeSort(int* a, int* aux, const int first, const int last) { if (first < last) { const int middle = (first + last) / 2; MergeSort(a, aux, first, middle); MergeSort(a, aux, middle + 1, last); Merge(a, aux, first, middle, last); } } int main(int argc, char** argv) { const int num_elements = 8; int a[num_elements] = { 11, 10, 13, 5, 8, 3, 2, 8 }; //int a[num_elements] = { 1, 5, 2, 4, 6, 3, 2, 6 }; int aux[num_elements + 2]; //多余的两个元素存放哨兵值INT_MAX printf("Before Sorting: \n"); PrintArrays(a, 8); MergeSort(a, aux, 0, 7); printf("After Sorting : \n"); PrintArrays(a, 8); return 0; }
3. 插入排序:
稳定排序,原址排序最好情况复杂度:O(n),当输入数组已经排好序时。
最坏情况复杂度:O(n^2),当输入数组为逆序时。
平均时间复杂度:O(n^2)
适合用于排序“元素数目较少的数组”。
#include <stdio.h> #include <stdlib.h> void PrintArrays(const int* a, const int num_elements) { for (int i = 0; i < num_elements; ++i) { printf("%d\t", a[i]); } printf("\n"); } void InsertionSort(int* a, const int length) { if (a == NULL || length <= 0) { fprintf(stderr, "Invalid Parameters!\n"); exit(EXIT_FAILURE); } for (int j = 1; j < length; ++j) { const int key = a[j]; int i = j - 1; while (i >= 0 && a[i] > key) { a[i + 1] = a[i]; --i; } a[i + 1] = key; } } int main(int argc, char** argv) { int a[8] = { 11, 10, 13, 5, 8, 3, 2, 8 }; printf("Before Sorting: \n"); PrintArrays(a, 8); InsertionSort(a, 8); printf("After Sorting : \n"); PrintArrays(a, 8); return 0; }
4. 计数排序:
稳定排序,非原址排序。最好情况复杂度:O(n+k)
最坏情况复杂度:O(n+k)
缺点:需要额外内存空间O(n+k)
基本思想:对每个输入的整数元素x(范围为:0-k),确定小于x的元素个数m。根据这一信息,可以直接把x放在输出数组的位置m+1上了。
#include <stdio.h> #include <stdlib.h> void PrintArrays(const int* a, const int num_elements) { for (int i = 0; i < num_elements; ++i) { printf("%d\t", a[i]); } printf("\n"); } void CountingSort(const int* a, int* output, const int length, const int k, const int first, const int last) { if (a == NULL || length <= 0) { fprintf(stderr, "Invalid Parameters!\n"); exit(EXIT_FAILURE); } int* counter = (int*)malloc((k+1)*sizeof(int)); for (int i = 0; i <= k; ++i) counter[i] = 0; for (int j = 0; j < length; ++j) ++counter[a[j]]; // 现在counter[i]存储值等于i的元素个数 for (int i = 1; i <= k; ++i) counter[i] += counter[i - 1]; // 现在counter[i]存储值小于等于i的元素个数 for (int j = length - 1; j >= 0; --j) { output[counter[a[j]] - 1] = a[j]; --counter[a[j]]; } free(counter); } int main(int argc, char** argv) { const int kMaxValue = 100; const int a[8] = { 11, 10, 13, 5, 8, 3, 2, 8 }; int output_a[8]; printf("Before Sorting: \n"); PrintArrays(a, 8); CountingSort(a, output_a, 8, kMaxValue, 0, 7); printf("After Sorting : \n"); PrintArrays(output_a, 8); return 0; }
5. 基数排序:
稳定排序,非原址排序。最好情况复杂度:O((n+k)d)
最坏情况复杂度:O((n+k)d)
基本思想: 将待比较整数的位数长度统一,数位较短的数值前面补零。从最低有效位开始逐位进行一次稳定排序,完成所有位数的排序后,该数列便成为一个有序序列。
6. 希尔排序:
希尔排序的运行时间依赖于增量序列的选取。最优时间复杂度:O( n*log(2n)
)
平均时间复杂度:希尔增量O(n^2),Hibbard增量O(n^3/2)
稳定性:不稳定
注:希尔排序算法是直接插入排序算法的一种改进。步长的选择很重要。只要最终步长为1的选择都可以工作,最后一步为步长为1的希尔排序-插入排序。
适用场景:中等大小规模,性能要求不高的场合。
#include <stdio.h> #include <stdlib.h> #include <time.h> void PrintArrays(const int* a, const int num_elements) { for (int i = 0; i < num_elements; ++i) { printf("%d\t", a[i]); } printf("\n"); } void ShellSort(int* array, const int len) { if (array == NULL || len <= 0) return; for (int gap = (len >> 1); gap > 0; gap >>= 1) { for (int i = gap; i < len; ++i) { for (int j = i - gap; j >= 0 && array[j] > array[j + gap]; j -= gap) { int temp = array[j]; array[j] = array[j + gap]; array[j + gap] = temp; } } } } int main(int argc, char** argv) { int a[8] = { 11, 10, 13, 5, 8, 3, 2, 8 }; printf("Before Sorting: \n"); PrintArrays(a, 8); ShellSort(a, 8); printf("After Sorting : \n"); PrintArrays(a, 8); return 0; }
相关文章推荐
- 排序算法之希尔排序<Shell_Sort>及其C语言代码实现
- 各类排序算法原理及其C语言实现
- 排序算法之堆排序<Heap_Sort>及其C语言代码实现
- 排序算法之快速排序<Quick_Sort>及其C语言代码实现
- 排序算法之冒泡排序<Bubble_Sort>及其C语言代码实现
- 常见排序算法及其C语言实现(二)
- 排序算法之归并排序<Merge_Sort>及其C语言代码实现
- C语言8种排序算法及其实现 1.希尔排序 2.二分插入法 3.直接插入法 4.带哨兵的直接排序法 5.冒泡排序 6.选择排序 7.快速排序 8.堆排序
- 排序算法之插入排序<Insertion_Sort>及其C语言代码实现
- 最快搜索算法之二分搜索,最快排序算法之快排【C语言实现】
- 用C语言实现常用排序算法
- 常见排序算法(冒泡,选择,快速)的C语言实现【修正版】
- 常见排序算法(冒泡,选择,快速)的C语言实现
- 几种常见排序算法的c语言实现
- 各种排序算法及其实现总结
- 各种排序算法及其java程序实现
- 常用排序算法之MERGE法与BUTTOMUPSORT法(C语言实现)
- 防脉冲干扰移动平均值法数字滤波器的C语言算法及其实现
- 各种排序算法及其java程序实现
- 排序二叉树及其遍历 c语言实现