************************************************************************************************************************************************************************************************ios
话很少说,直接进入正题:c++
代码实现以下:(以正序输出为例,倒序输出,仅需对代码进行适当修改便可)程序员
#include<bits/stdc++.h> #include<algorithm> using namespace std; int a[100055]; int main() { int n,i; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; } int head; head = 2; while(head<=n) { i = head; while(i>=2&&a[i]<a[i-1]) { if(a[i]<a[i-1])//判断是否进行交换 { swap(a[i] ,a[i-1]);//调用swap函数 i--; } } head++;//起索引做用,是循环的范围加1 } for(i=1;i<=n;i++) { cout<<a[i]; } return 0; }
上述代码的运行结果为:算法
首先,咱们来理一下上述代码的思想,上述代码实际上就是,每次while循环依次比较a[2]与a[1] ; a[3]与a[2] 、a[2]与a[1] ; a[4]与a[3]、a[3]与a[2]、a[2]与a[1] ; ………大小,直到遍历完数组全部的元素,也就完成了排序。数组
咱们能够把上述代码总结成一种模型,即,上述代码能够对任意一组数据的任意一段连续数据进行排序(仅需改变上述代码的初始化条件以及循环结束条件便可实现),而这一思想的典型应用就是 “滚动的榜单”问题。函数
固然,上述代码也能够用for循环实现,但我的认为,用while循环,更能体现其思想本质,尤为是经过变量head,体现比较范围的变换。且在实际应用时,我的感受,用while循环实现更加方便。学习
代码以下(以正序输出为例)ui
#include<bits/stdc++.h> #include<algorithm> using namespace std; int a[55]; int main() { int n,i; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; } int head = 1; while(head<=n) { for(i=head+1;i<=n;i++) { if(a[i]<a[head]) { swap(a[i] ,a[head]); } } head++; } for(i=1;i<=n;i++) { cout<<a[i]; } return 0; }
上述代码的运行结果为:spa
上述代码的思想是:首先,用数组的第一个元素与剩下的元素比较,并将最小的元素调到第一位;而后,用数组的第二个元素与剩下的元素比较,并将最小的元素调到第二位;以此类推,当head等于n时,就完成了排序。设计
上述算法,对于不搞竞赛的同窗来讲,应该是最经常使用的排序方法了。
上述代码一样能够用for循环实现。
具体代码以下(以升序形式输出)
#include<iostream> #include<algorithm> using namespace std; void quicksort(int l ,int r); int a[100055]; int main() { int n,i; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; } quicksort(1 ,n); for(i=1;i<=n;i++) { cout<<a[i]<<" "; } cout<<endl; return 0; } void quicksort(int l ,int r) { int i,j,m,mid; i = l; j = r;
mid = (l+r)/2; m = a[mid];//将数组分红两部分 while(i<=j) {
/***********************************************/
//注意,这里while里面的判断条件为何不带上 “=”?
//是为了防止当出现数组中出现一段相等的数字是,该循环变为死循环。以下面举出的例子。 while(a[i]<m) i++; while(a[j]>m) j--;
/***********************************************/ if(i<=j) { swap(a[i] ,a[j]); i++; j--; } } if(j-l>=1)//中止调用函数自己的判断条件 quicksort(l ,j);//经过调用函数自身,对分开的两部分,分别进行排序
//同时,因为i,j通过while循环,均越过了中值mid,故,新范围是(l ,j),下面的(i,r)同理。 if(r-i>=1)//中止调用函数自己的判断条件 quicksort(i ,r);//经过调用函数自身,对分开的两部分,分别进行排序 }
上述代码运行结果为:
但当将while循环中的判断条件带上等号是,就会出现漏洞,可能使程序变为死循环,如:
上述代码实际上体现了二分的思想:首先随机在数组中选一个数,将一个数组分红随机分红两部分(这里我就用区间的中间位置对应的值,实际上,能够用rand函数随机生成一个位置,这样其实更加合理),分别在左,右取大于或等于、小于或等于a[mid]的数,进行交换,直到i,j越过mid值时,一次循环结束。这样不断地进行循环,最终便可以实现排序。
快速排序的精髓就在于灵活应用二分的思想,这也正是其运行效率高的缘由之一。
代码以下:(以升序为例)
上述代码运行结果为:
上述代码的核心思想是:先将数组利用二分思想屡次进行二等分,而后在从获得的各个小份数组出发,两两遵循在合并的同时按从小到大排序,最终,便可实现排序。
具体图片以下:(下图摘自百度百科 ,连接:https://baike.baidu.com/pic/归并排序/1639015/0/c8177f3e6709c93d673b9ed49d3df8dcd00054c3
fr=lemma&ct=single#aid=0&pic=c8177f3e6709c93d673b9ed49d3df8dcd00054c3)
归并排序在上述几种排序方式中应该是最复杂的排序方式了,但其高效的运行效率,以及其包含的重要思想使得做为一个合格的程序员,或者是搞算法竞赛的同窗必须掌握。
到目前为止,我的感受,对上述归并排序算法的思想的应用最到位的当属经典的 “ 逆序数的对数” 问题。
除了介绍上述四种经常使用的排序方法外,我还想补充一下关于二分法查找的一下东西。(将一个数加入到一组数里面后,找出其在这组数里的位置)
先看代码实现:(以正序输入为例)
以上代码运行结果为:
若没有上述语句,会:
结果是乱码!!!
因此,咱们在设计二分法的时候,必定要考虑当输入的值大于已知的最大值这种状况,固然,解决这个问题的方法不止上面一种,就不一一罗列了。
*************************************************************************************************************************************************************************************************************************
再强调一次,以上代码均为 经过各类途径学习+本身的理解 所得,如若侵权,请告知,核实以后,必当即删除!!!
同时本人为大一菜鸟,上面的样例均为自主设置的,如如有误,还请告知,必当即改正。
本人写此文章主要目的是对知识点整理,但限于我的水平,如上述表述内容有些许错误,或不到位的地方,请各位大佬告知,在下必马上更改!!!
欢迎大佬们评论,留言。
最后,码字不易,要是感受还行的话,求求大佬们点个赞吧。