C语言:排序算法
2015-09-28 10:46
375 查看
本节中所讲的排序均以升序为例。
一、冒泡排序
1. 基本思想:
从左到右,两两比较;如果发现前者比后者大,则交换元素。每一轮比较完毕后,序列中最大的一个元素会至于最后。流程图如下:
2. 代码清单:
二、选择排序
1. 基本思想:
每次循环的时候,找出数组中最小的元素,并且与循环操作中数组最前面的元素进行交换。流程图如下:
2. 代码清单:
三、插入排序
1. 基本思想:
每次假定数组第一个元素为在正确的位置上面,然后在数组后面依次寻找比这个元素大得并且是最小的那个元素,将其插入到指定元素的后面,与此同时,那些原本紧挨着指定元素后面的所有元素,依次往后移动一个位置。
2. 代码清单:
四、归并排序
1. 基本思想:
将一个数组分解成多个数组,依次对每个子数组进行排序,最终将排序完成的子数组合并,进行最终的排序。
2. 代码清单:
五、快速排序
1. 基本思想:
假设用户输入了如下数组:
创建变量i=0(指向第一个数据), j=5(指向最后一个数据), k=6(赋值为第一个数据的值)。
我们要把所有比k小的数移动到k的左面,所以我们可以开始寻找比6小的数,从j开始,从右往左找,不断递减变量j的值,我们找到第一个下标3的数据比6小,于是把数据3移到下标0的位置,把下标0的数据6移到下标3,完成第一次比较:
i=0 j=3 k=6
接着,开始第二次比较,这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2的数据是第一个比k大的,于是用下标2的数据7和j指向的下标3的数据的6做交换,数据状态变成下表:
i=2 j=3 k=6
称上面两次比较为一个循环。
接着,再递减变量j,不断重复进行上面的循环比较。
在本例中,我们进行一次循环,就发现i和j“碰头”了:他们都指向了下标2。于是,第一遍比较结束。得到结果如下,凡是k(=6)左边的数都比它小,凡是k右边的数都比它大:
如果i和j没有碰头的话,就递加i找大的,还没有,就再递减j找小的,如此反复,不断循环。注意判断和寻找是同时进行的。
然后,对k两边的数据,再分组分别进行上述的过程,直到不能再分组为止。
2. 代码清单:
一、冒泡排序
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 |
我们要把所有比k小的数移动到k的左面,所以我们可以开始寻找比6小的数,从j开始,从右往左找,不断递减变量j的值,我们找到第一个下标3的数据比6小,于是把数据3移到下标0的位置,把下标0的数据6移到下标3,完成第一次比较:
下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数据 | 3 | 2 | 7 | 6 | 8 | 9 |
接着,开始第二次比较,这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2的数据是第一个比k大的,于是用下标2的数据7和j指向的下标3的数据的6做交换,数据状态变成下表:
下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数据 | 3 | 2 | 6 | 7 | 8 | 9 |
称上面两次比较为一个循环。
接着,再递减变量j,不断重复进行上面的循环比较。
在本例中,我们进行一次循环,就发现i和j“碰头”了:他们都指向了下标2。于是,第一遍比较结束。得到结果如下,凡是k(=6)左边的数都比它小,凡是k右边的数都比它大:
下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数据 | 3 | 2 | 6 | 7 | 8 | 9 |
然后,对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; }
相关文章推荐
- C++ int main(int argc,char* argv[])详解
- c++笔试题-输入n,输出对应的所有长度为n的二进制串
- C/C++语言杂谈
- C++ 墙角知识 04
- c++ typedef类型定义
- c++ 初始化
- 黑马程序员——C语言日志——typedef的使用以及和#define的区别
- C++ STL简化了编程
- 【Visual C++ 2010】如何快速将Win32程序改为控制台程序
- C++ OOP面向对象
- 解决C++编译出现的重定义问题:multiple definition of ’XXX‘错误
- 为什么C++中空类和空结构体大小为1?(转载)
- C语言链表常见基本操作
- 【Visual C++ 2010】Unicode和ANSI的一些注意事项
- C++学习笔记1--基础知识
- 【转】最值得你所关注的10个C语言开源项目
- 如何在Qt C++中解析JSON数据并使之被QML应用
- n皇后2种解题思路与代码-Java与C++实现
- C/C++:对象初始化相关
- [C++ primer]第一章 开始