若本轮发生了交换,则重复上一步
O(N^2)
#include <iostream> #include <algorithm> using namespace std; void sort(int *a,int n) { bool changed = false; do { changed = false; for(int i =1; i <= n; i++) { if(a[i-1] > a[i]) { swap(a[i-1],a[i]); changed = true; } } --n;// 优化:每轮都把最大的排到最后了,所以每次循环时都可以少比较一次 }while(changed); }
第二个数据开始,循环到最后一个数为止:
(从把每个数据插入适当位置)
1 找适当位置:和左边的数比较,直到左边的数据不比它大或左边没位置
2 插入在找到的位置
这两步有重复的地方 所以在比较时顺便移位
插入法比冒泡法要快很多 因为冒泡里面有大量的交换操作(交换要3步 移动只要1步)
但两者时间复杂度是一样的 O(N^2)
如果只有少量乱序时 冒泡法很快
void sort( int *a,int n ) { int j;//因为循环完毕后还要用到j for( int i=1;i <n; i++ ) //从第二个开始 a[1] { int t = a[i]; //保存要插入的数据 for(j= i; j>0 && t<a[j-1] ; j-- ) //和左边的比较 如果这个数比左边的小 将左边的右移一位 { a[j] = a[j-1]; //右移 } a[j] = t; } }
#include <algorithm> using namespace std; void sort(int *a,int n) { int min; int j; for(int i=0;i<n-1;i++) //只做n-1次循环 因为最后一个肯定是最大的 { min = i; for( j =i; j<n;j++) { if(a[j] < a[min]) { min = j; } } swap(a[i],a[min]); } }
快速排序:
O(NlgN)
元素个数不超过一个时直接完成:如果L<R,交换 L R指向的数值
代码学习要点:
1 向左向右查找时要防止越界
2 指针的比较 指针的减法
#include <algorithm> using namespace std; void sort(int *a,int n) { if(n <=1) return; if(n==2) { if(a[0] > a[1]) { swap(a[0],a[1]); } return; } //3个以上才用快排 int jie = a[n/2]; //选取中间的做分界值 swap(a[0],a[n/2]); //将分界值调换到左边来 int *L = a+1,*R = a+n-1; while(L < R) { //从左向右走 while(*L < jie && L<R) //谨防L越界 先移L ,R是界 { ++L; } //从左向右走 while(*R >= jie && R >a) //谨防R越界 边界是a { --R; } if(L < R) { swap(*L,*R); } } if(*R < jie) { swap(*R,a[0]); } sort(a,R-a); sort(R+1,n-1-(R-a)); }