插入排序
基本思想:
将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
要点:设立哨兵,作为临时存储和判断数组边界之用。
- void InsertSort(int a[], int n)
- {
- for(int i= 1; i<n; i++){
- if(a[i] < a[i-1]){ //若第i个元素大于i-1元素,直接插入。小于的话,移动有序表后插入
- int j= i-1;
- int x = a[i]; //复制为哨兵,即存储待排序元素
- a[i] = a[i-1]; //先后移一个元素
- while(x < a[j]){ //查找在有序表的插入位置
- a[j+1] = a[j];
- j--; //元素后移
- }
- a[j+1] = x; //插入到正确位置
- }
- print(a,n,i); //打印每趟排序的结果
- }
- }
希尔排序
基本思想:
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
操作方法:
- 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列个数k,对序列进行k 趟排序;
- 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
- void ShellInsertSort(int a[], int n, int dk)
- {
- for(int i= dk; i<n; ++i){
- if(a[i] < a[i-dk]){ //若第i个元素大于i-1元素,直接插入。小于的话,移动有序表后插入
- int j = i-dk;
- int x = a[i]; //复制为哨兵,即存储待排序元素
- a[i] = a[i-dk]; //首先后移一个元素
- while(x < a[j]){ //查找在有序表的插入位置
- a[j+dk] = a[j];
- j -= dk; //元素后移
- }
- a[j+dk] = x; //插入到正确位置
- }
- print(a, n,i );
- }
- }
- /**
- * 先按增量d(n/2,n为要排序数的个数进行希尔排序
- *
- */
- void shellSort(int a[], int n){
- int dk = n/2;
- while( dk >= 1 ){
- ShellInsertSort(a, n, dk);
- dk = dk/2;
- }
- }
选择排序
基本思想:
在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
- int SelectMinKey(int a[], int n, int i)
- {
- int k = i;
- for(int j=i+1 ;j< n; ++j) {
- if(a[k] > a[j]) k = j;
- }
- return k;
- }
- /**
- * 选择排序
- *
- */
- void selectSort(int a[], int n){
- int key, tmp;
- for(int i = 0; i< n; ++i) {
- key = SelectMinKey(a, n,i); //选择最小的元素
- if(key != i){
- tmp = a[i]; a[i] = a[key]; a[key] = tmp; //最小元素与第i位置元素互换
- }
- print(a, n , i);
- }
- }
冒泡排序
基本思想:
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
- void bubbleSort(int a[], int n){
- for(int i =0 ; i< n-1; ++i) {
- for(int j = 0; j < n-i-1; ++j) {
- if(a[j] > a[j+1])
- {
- int tmp = a[j] ; a[j] = a[j+1] ; a[j+1] = tmp;
- }
- }
- }
- }
快速排序
1)选择一个基准元素,通常选择第一个元素或者最后一个元素,
2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。
3)此时基准元素在其排好序后的正确位置
4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。
- void swap(int *a, int *b)
- {
- int tmp = *a;
- *a = *b;
- *b = tmp;
- }
- int partition(int a[], int low, int high)
- {
- int privotKey = a[low]; //基准元素
- while(low < high){ //从表的两端交替地向中间扫描
- while(low < high && a[high] >= privotKey) --high; //从high 所指位置向前搜索,至多到low+1 位置。将比基准元素小的交换到低端
- swap(&a[low], &a[high]);
- while(low < high && a[low] <= privotKey ) ++low;
- swap(&a[low], &a[high]);
- }
- print(a,10);
- return low;
- }
- void qsort_improve(int r[ ],int low,int high, int k){
- if( high -low > k ) { //长度大于k时递归, k为指定的数
- int pivot = partition(r, low, high); // 调用的Partition算法保持不变
- qsort_improve(r, low, pivot - 1,k);
- qsort_improve(r, pivot + 1, high,k);
- }
- }
- void quickSort(int r[], int n, int k){
- qsort_improve(r,0,n,k);//先调用改进算法Qsort使之基本有序
- //再用插入排序对基本有序序列排序
- for(int i=1; i<=n;i ++){
- int tmp = r[i];
- int j=i-1;
- while(tmp < r[j]){
- r[j+1]=r[j]; j=j-1;
- }
- r[j+1] = tmp;
- }
- }