在挑战问题之前,排序是相当重要的,至此我写一篇文章来记录我初学排序的感想。
首先是选择排序法,选择排序就是从头开始选出最小的值的位置,然后将该位置的元素与未排序的起始元素进行交换。
选择排序法的复杂度数量级为O(N^2)。
而且由于选择排序法会直接交换两个不相邻的元素,所以属于不稳定的排序法。
//选择排序法 #include<stdio.h> void select_sort(int *a , int n); int a[1000]; int main() { int i,j,n,index,temp; scanf("%d",&n); for(i=0;i<n;i++) scanf("%d",&a[i]); select_sort(a,n); for(i=0;i<n;i++) { if(i>0)printf(" ");//保证每个数字(除了最后一个)后面都有空格 printf("%d",a[i]); } return 0; } void select_sort(int *a , int n) { int i,temp,index,j; for(i=0;i<n-1;i++) { index=i;//用来记录最小值的下标 for(j=i+1;j<n;j++) if(a[index]>a[j])index=j; temp=a[index]; a[index]=a[i]; a[i]=temp; } }
第二
冒泡排序法,冒泡排序的思想就是将小的数字逐渐冒泡到开头,是相邻元素进行比较和交换,因此键相同的元素不会改变顺序,所以冒泡
排序法属于一种稳定的算法。
冒泡排序法的复杂度数量和选择排序法一样是O(N^2)。
值得一提的是冒泡排序法中的交换次数又称为反序数或逆序数,可用于体现数列的错乱程度。
冒泡排序法,有两种比较流行的写法。
//冒泡排序法 #include<stdio.h> int bubble_sort(int *a , int n); int a[1000]; int main() { int i,j,temp,n,reverse; scanf("%d",&n); for(i=0;i<n;i++) scanf("%d",&a[i]); reverse=bubble_sort(a,n); for(i=0;i<n;i++) { if(i>0)printf(" "); printf("%d",a[i]); } printf("\n"); printf("%d",reverse); return 0; } int bubble_sort(int *a , int n) { int temp,count=0;//temp为交换,count用来计算逆序数 for(int i=1;i<n;i++) { for(int j=0;j<n-i;j++) { if(a[j]>a[j+1]) { temp=a[j+1]; a[j+1]=a[j]; a[j]=temp; count++; } } } return count; }
//冒泡flag版 #include<stdio.h> int bubble_sort(int *a,int n); int a[1000]; int main() { int i,n,reverse; scanf("%d",&n); for(i=0;i<n;i++) scanf("%d",&a[i]); reverse=bubble_sort(a,n); for(i=0;i<n;i++) { if(i>0)printf(" "); printf("%d",a[i]); } printf("\n"); printf("%d",reverse); return 0; } int bubble_sort(int *a,int n) { bool flag=1; int i,j,temp,count=0; for(i=0;flag;i++) { flag=0; for(j=n-1;j>i;j--) { if(a[j]<a[j-1]) { temp=a[j-1]; a[j-1]=a[j]; a[j]=temp; flag=1; count++; } } } return count; }
第三
接下来就要谈到了插入排序法。
思路就是将数字分别插入到已排好序的手牌中的适当位置,重复这一操作直到插入最后一张牌,整个排序就完成了。
而插入排序法是一种很有趣的算法,输入数据的顺序能大幅度的影响到它的复杂度。只有降序排列时,复杂度才为O(N^2)。
如果为升序排序,复杂度仅有N。可见插入排序的优势在于能快速处理相对有序的数据。
//插入排序法 #include<stdio.h> void trace(int *a,int n);//用来记录每一次排完序以后的样子 void insertion_sort(int *a,int n); int a[1000]; int main() { int i,n; scanf("%d",&n); for(i=0;i<n;i++) scanf("%d",&a[i]); trace(a,n); insertion_sort(a,n); return 0; } void trace(int *a,int n) { int i; for(i=0;i<n;i++) { if(i>0)printf(" "); printf("%d",a[i]); } printf("\n"); } void insertion_sort(int *a,int n) { int temp,i,j; for(i=1;i<n;i++) { temp=a[i];//记录要插入的数据 j=i-1; while(j>=0&&a[j]>temp) { a[j+1]=a[j];//插入的地方每一位都向后移动一位 j--; } a[j+1]=temp;//插入数据 trace(a,n);//输出每一步的情况 } }
对于排序时稳定性的判断
冒泡排序法是稳定的,而选择排序法是不稳定的,可以比较两种方法排序后的结果来判断选择排序在什么情况下是稳定的。
第四
要说的是C++里面自带的STL库中的sort函数
对给定区间所有元素进行排序。头文件是#include <algorithm>
学会了这种方法也打消我学习c++以来使用的冒泡排序和选择排序所带来的执行效率不高的问题!
因为它使用的排序方法是类似于快排的方法,时间复杂度为n*log2(n),执行效率较高!
时间复杂度仅有n*log2(n)!多牛啊!而且它的用法简单!代码量少!
#include<iostream> #include<algorithm> using namespace std; int a[1000]; int main() { int n,i; cin >> n; for(i=0;i<n;i++) cin >> a[i]; sort(a,a+n); for(i=0;i<n;i++) { if(i>0)cout << " "; cout << a[i]; } return 0; }
当然在排序里面还有其他的算法。
例如希尔排序法,归并排序法。
所以我们还要加强自身,学习更多的方法。
待我学好这些,日后继续更新。
—————————————————————————————————————————————————吾不识青天高,黄地厚,怎耐日寒月暖,来煎人寿!