关于排序
来源:互联网 发布:数据有效性设置 编辑:程序博客网 时间:2024/06/18 06:40
编译器版本:vs2013
排序的目的
::如果输入一系列数字a1,a2,a3,a4,a5,a6,a7
经过排序有
::输出a1< a2< a3< a4< a5< a6< a7或者
::输出a1>a2>a3>a4>a5>a6 >a7
即让一系列无序数字从大到小或者从小到大有序即为排序。
学习中的几种排序算法
1:插入排序
基本思想:
升序:给一个数组,并不知道是否有序,从第二个数开始依次往后直到数组最后一个元素,挨个和前面那个数比大小,大的放这个数后面,小的接着和前面数比,如果比前面每一个数都小,就放在最前面,依次循环比完每一个数。
降序和升序思想一致,只是要把大的放在前面,小的放在后面。
具体代码
void Insertsort(int* a, size_t n){ assert(a); for (size_t i = 0; i<n - 1; ++i) { int end = i; int tmp = a[end + 1]; while (end >= 0) { if (a[end] > tmp) { a[end + 1] = a[end]; --end; } else { break; } } a[end + 1] = tmp; }}
给一个整型数组a,数组元素n个,首先assert数组不能为空,空数组不需要排序,
i是下标,从0开始,上图中每一个b都是在所画圆圈区域内即将要插入得数,思想在上面已经讲过,就是每一个即将要插入的数和前面的数相比,比前面一个数大就差到那个数后面,找不到要插入的位置就需要一直找,找完已经排序完成的所有数为止,当然,既然是插入,在插入一个新的数以后,排在这个数后面的那些书当然要往后挪一下位置了。
2:希尔排序
希尔排序就是升级版的插入排序,在中间加了一个间距gap,只是为了更快的将前面的大数据和后面的小数据换回来,达到的效果是预排序,
假如gap=3,那么就是在这个数组中隔三个数做排序,这样可以尽快把后面的小数据和前面的大数据交换,思想和前面的插入排序一样
void shellsort(int* a, size_t n){ assert(a); int gap = 3; for (size_t i = 0; i < n - gap; ++i) { int end = i; int tmp = a[end + gap]; while (end >= 0) { if (a[end] > tmp) { a[end + gap] = a[end]; end -= gap; } else { break; } } a[end + gap] = tmp; }}
end=i; tmp=a[end+gap]; 要插入的新元素是tmp,tmp先和前面的a[end]比较,若a[end]大,将a[end]往后挪,end-=gap;再比,知道不满足while或者if条件,a[end + gap] = tmp;完成插入;
3:选择排序
具体思想:升序–给一个无序数组,min和max分别表示数组中最小和最大数的下标,两个都是从0下标开始,找到两个数以后,最小值换到0下标位置,最大值换到n-1下标位置,
void Selectsort(int* a, size_t n)//选下标{ assert(a); size_t left = 0; size_t right = n - 1; while (left < right) { size_t min = left, max = left; for (size_t i = left; i < right; ++i) { if (a[i]< a[min]) { min = i; } if (a[i] > a[max]) { max = i; } swap(a[min], a[left]); //9 0 1 2 4 5 7 //下面这个if条件判断的就是类似上面这类情况,此时min是 //数组元素0的下标,left是9的下标同时也是数组最大元素9 //的下标,把0和9交换以后,9的下标即刚才交换之前0的下标 //而把最小值换到最左边以后需要做的就是把最大值换到最右边 //最大值现在是9,即a[min],所以需要把max赋值为min和最 //右边交换,然后--left,--right,在剩下的数里面找最大最 //小接着上面的操作 if (max == left) { max = min; } swap(a[max], a[right]); ++left; --right; } }}
4:快速排序
具体思想:就是把数组通过多次划分成小区间,甚至这个小区间里面就一个数,把小区间划分排序成有序区间再组合起来就是一个大的有序数组。
int Partsort1(int *a, int left, int right) //挖坑{ int key = a[right]; int begin = left; int end = right; while (begin < end) { while (a[begin] <= key) { ++begin; } if (begin < end) { swap(a[end], a[begin]); } while (a[end] >= key) { --end; } if (begin < end) { swap(a[begin], a[end]); } } swap(a[begin], a[right]); return begin;}int Partsort2(int *a,int left,int right) //左右指针{ int key = a[right]; while (left < right) { while (left < right&&a[left] <= key) { ++left; } a[right] = a[left]; while (left < right&&a[left] >= key) { --right; } a[left] = a[right]; } a[left] = key;}int Partsort3(int *a, int left, int right) //前后指针{ int cur = left; int key = a[right]; int prev = left - 1; while (cur < right) { if (a[cur] < a[key] && ++prev != cur) { swap(a[prev], a[cur]); } ++cur; } swap(a[++prev], a[right]); return prev;}void Quicksort(int *a, int left, int right){ assert(a); if (left >= right) { return; } else { int div = Partsort1(a, left, right); int div = Partsort2(a, left, right); int div = Partsort3(a, left, right); Quicksort(a, left, div - 1); Quicksort(a, div + 1, right); }}
5:快排非递归实现
具体思想:利用stack先入后出,实现数组划分成小区间,小区间依次排序实现有序并合并以后实现大数组有序。
int Partsort1(int *a, int left, int right) //挖坑{ int key = a[right]; int begin = left; int end = right; while (begin < end) { while (a[begin] <= key) { ++begin; } if (begin < end) { swap(a[end], a[begin]); } while (a[end] >= key) { --end; } if (begin < end) { swap(a[begin], a[end]); } } swap(a[begin], a[right]); return begin;}int Partsort2(int *a,int left,int right) //左右指针{ int key = a[right]; while (left < right) { while (left < right&&a[left] <= key) { ++left; } a[right] = a[left]; while (left < right&&a[left] >= key) { --right; } a[left] = a[right]; } a[left] = key;}int Partsort3(int *a, int left, int right) //前后指针{ int cur = left; int key = a[right]; int prev = left - 1; while (cur < right) { if (a[cur] < a[key] && ++prev != cur) { swap(a[prev], a[cur]); } ++cur; } swap(a[++prev], a[right]); return prev;}void Quicksort(int *a, int left, int right){ assert(a); if (left >= right) { return; } else { int div = Partsort1(a, left, right); int div = Partsort2(a, left, right); int div = Partsort3(a, left, right); Quicksort(a, left, div - 1); Quicksort(a, div + 1, right); }}void Quicksort(int *a, int left, int right){ stack<int> s; if (left < right) { s.push(right); s.push(right); while (s.empty()) { int begin = s.top(); s.pop(); int end = s.top(); s.pop(); int div = part1(a, begin, end); int div = part2(a, begin, end); int div = part3(a, begin, end); if (begin < div - 1) { s.push(div - 1); s.push(begin); } if (div + 1 < end) { s.push(end); s.push(div + 1); } } }}
6:归并排序
基本思想:归并排序有点类似于合并两个有序链表
归并排序是建立在归并操作上的一种有效的排序算法,该算法和快速排序都是采用分治法来设计算法的,区别在于归并排序把数组分为两个基本等长(最多相差一个元素)的子数组,分别排好序之后还要进行归并操作,而快速排序在拆分子数组的时候则有所不同,其取一个基准元素,拆分之后基准元素左边的元素都比基准元素小,右边的元素都不小于基准元素,这样只需要分别对两个子数组排序即可,不再像归并排序一样需要归并操作。归并排序是稳定的算法,其最坏的时间复杂度是O(n^2),其最好的时间复杂度是O(nlogn).
假设有数组 a,比较 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].
void _Merge(int *a, int* tmp, int begin1, int end1, int begin2, int end2){ size_t index = begin1; size_t pos = begin2; while (begin1 < end1&&begin2 < end2) { if (a[begin1] < a[begin2]) { tmp[index++] = a[begin1++]; } else { tmp[pos++] = a[begin2++]; } } if (begin1 >= end1) { while (begin2 < end2) { tmp[pos++] = a[begin2++]; } } else if (begin2 >= end2) { while (begin1<end1) { tmp[index++] = a[begin1++]; } } else { return; } memcpy(a + pos, tmp + pos, sizeof(int)*(end2 - pos + 1));}void _Mergesort(int*a, int *tmp, int left, int right){ if (left >= right) { return; } else { int mid = left + (left + right) / 2; _Mergesort(a, tmp, left, mid); _Mergesort(a, tmp, mid + 1, right); _Merge(a, tmp, left, mid, mid + 1, right); }}void Mergesort(int *a, size_t n){ assert(a); int *tmp = new int[n]; _Mergesort(a, tmp, 0, n - 1);}
7:冒泡排序
基本思想:即对相邻两个数进行比较,如果反序就交换位置,直到整个序列没有出现反序为止。
代码里面的flag是优化部分,如果第一趟没有发现有交换产生,则直接跳出循环,
void Bubble_sort(int *a, size_t n){ int i, j, temp; bool flag = true; for (i = n - 1; i >= 0; i--) { flag = false; for (j = 0; j < i; j++) { if (a[j] >a[j + 1]) { temp = a[j + 1]; a[j + 1] = a[j]; a[j] = temp; flag = true; } if (flag == false) break; } }}
- 关于排序
- 关于排序
- 关于排序
- 关于排序
- 关于排序
- 关于排序
- 关于排序
- 关于排序
- 关于排序
- 关于排序
- 关于排序
- 关于排序之交换排序
- 关于排序之选择排序
- 关于IList的排序
- STL关于排序
- 关于排序算法
- 关于文件名排序算法
- 关于位图排序
- ubuntu下解决apt-get install php5-mcrypt后php -m phpinfo 没显示的问题
- android DateUtils
- 离散Hopfield神经网络的联想记忆
- js对象构造函数用法
- @synthesize 的作用
- 关于排序
- TCP端口状态说明ESTABLISHED、TIME_WAIT
- 【最短路->DP】SPOJ(ACPC13)[Increasing Shortest Path]题解
- Java中获取键盘输入值的三种方法
- android RatingBar自定义图片
- 数位DP的第一次试水(HDU 2089)
- 吐血推荐珍藏的 Chrome 插件二
- JS复制内容到剪贴板
- eslint: prop type 'object' is forbidden(react/forbid-prop-types)