冒泡排序,快速排序

Posted on 2018-12-25 17:39  金色的省略号  阅读(399)  评论(0编辑  收藏  举报

   一、冒泡排序法(bubble sort)的基本思想是,通过相邻两个记录 之间的比较和交换,使关键码较小的记录逐渐从底部移向顶 部(上升),关键码较大的记录逐渐从顶部移向底部(沉 底),冒泡由此得名;冒泡排序属于交换类排序

   排序算法是稳定的,数组存储或链表存储都可以冒泡排序,冒泡排序最好情况的时间复杂度O(N),最坏情况的时间复杂度是O(N2),对于N个数进行冒泡排序,最坏情况下需要进行的比较次数为N*(N-1)/2

  

/*冒泡排序--双重循环*/
void BubbleSort(int arr[],int n)
{
    int i, j;
    for(i=0; i<n-1; ++i)
        for(j=0; j<n-i-1; ++j)
            if(arr[j]<arr[j+1]){
                int t = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = t;
            }
}

 

/* 冒泡排序--优化双重循环 */
#include <stdio.h>

void swap(int *a, int *b){
    int t = *a;
    *a = *b; 
    *b = t;
}

void bubbleSort(int *a, int n){
    for(int i=n-1, swapped = 1; i>=1 && swapped; --i){ //比较n-1趟 并 控制下标
        swapped = 0; 
        for(int j=0; j<i; ++j){ //每趟相邻元素两两比较, 最大下标 n-1 
            if(a[j]>a[j+1]){
                swap(&a[j],&a[j+1]);
                swapped = 1;//是否发生交换的标志
            }
        }
    }
}

int main()
{
    int arr[10] = {6,5,4,3,2,1}; //{1,2,3,4,5,6};
    bubbleSort(arr,6);
    for(int i=0; i<6; ++i){
        printf("%d\t", arr[i]);
    }
    return 0;
}

 

/*冒泡排序--下标left至下标right*/
void BubbleSort(int arr[],int left, int right)
{
    if(right > left){
        int i, j;
        for(i=0; i<right-left; ++i)
            for(j=left; j<right-i; ++j)
                if(arr[j]<arr[j+1]){
                    int t = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = t;
                }
    }
}

 

/*冒泡排序--递归*/
void BubbleSort(int *a,int left, int right)
{
    if(left<right){
        int j,t; 
        for(j=right; left<j; j--){
            if(a[j-1]>a[j])/*相邻比较*/ 
                t=a[j],a[j]=a[j-1],a[j-1]=t;  
        }
        BubbleSort(a,j+1,right);/*递归*/
    }
}

  二、快速排序

  选择一个基数,把待排序的数据分成左边比它小、右边比它大两个部分,再对左边、右边的数据以此类推,最终完成排序。快速排序属于交换类排序,算法不稳定

  1、交换法

  以数组左边的第一个数据为基数,设定左指针指向基数,设定右指针指向数组最右边的数据,在左右指针不出界的情况下,向右移动左指针找到比基数大的数停下,向左移动右指针找到比基数小的停下,在左指针小于右指针的情况下,交换两个数,循环左右指针的移动和数据交换,一旦左指针小于右指针的条件不成立(右指针指向数据一定不大于基数),基数与右指针指向的数据交换,基数有序位置确定,即基数左边小右边大;基数左右数据以此类推,递归完成排序。

 1 /*快速排序*/
 2 #include <stdio.h>
 3 void QuickSort(int *a,int n, int left, int right)
 4 {
 5     int i,j,t; 
 6         /*左指针left指向数组头 右指针right指向数组尾*/
 7     if(left<right){
 8         i=left,j=right+1;/*左右指针*/
 9         while(i<j){
10             while(i+1<n && a[++i]<a[left]);/*左指针右移 指向大于基数的数据停止*/
11             while(j-1>-1 && a[--j]>a[left]);/*右指针左移 指向小于基数的数据停止*/
12             if(i<j)/*满足左指针小于右指针的条件 两指针指向数据交换*/
13                 t=a[i],a[i]=a[j],a[j]=t;         
14         }
15         t=a[left],a[left]=a[j],a[j]=t;/*右指针指向数据与基数交换*/
16         QuickSort(a,n,left,j-1);/*左边数据递归*/
17         QuickSort(a,n,j+1,right);/*右边数据递归*/
18     }
19 }
20 
21 int main()
22 {
23     int i, arr[5]={20,40,0,15,60};
24     QuickSort(arr,5,0,4);
25     for(i=0; i<5; ++i)
26         printf("%d ",arr[i]);
27     printf("\n");
28     return 0;
29 }

  2、补空位法

  设定左右指针分别指向数组的头、尾,以最左边的数为基数,提取保存,左指针指向的基数位为空位,在右指针大于左指针的条件下,向左移动右指针,一旦发现比基数小的数据,该数据赋值到左指针指向的空位,右指针指向的为空位,在左指针小于右指针的条件下,向右移动左指针,一旦发现比基数大的数,该数据赋值到右指针指向的空位,左指针指向的位置为空位,一旦左指针不小于右指针,把基数赋值到右指针所指空位,基数有序定位,即基数左边小、右边大;基数左右数据以此类推,递归完成排序。

 1 /*快速排序*/
 2 #include <stdio.h>
 3 
 4 void QuickSort(int *a, int left, int right)
 5 {
 6     int i,j,t;
 7     /*左指针left指向数组头 右指针right指向数组尾*/
 8     if(left<right){
 9         i=left,j=right,t=a[left];/*左右指针 提取基数*/
10         while(i<j){
11             while(i<j && a[j]>=t) j--;/*右指针左移 指向小于基数的数据停止*/
12                 a[i]=a[j]; /*补空位*/
13             while(i<j && a[i]<=t) i++;/*左指针右移 指向大于基数的数据停止*/
14                 a[j]=a[i]; /*补空位*/
15         }
16         a[j]=t;/*右指针指向数据即基数应在的位置 基数定位*/
17         QuickSort(a,left,j-1);/*左边数据递归*/
18         QuickSort(a,j+1,right);/*右边数据递归*/
19     }
20 }
21 
22 int main()
23 {
24     int i, arr[5]={20,40,0,15,60};
25     QuickSort(arr,0,4);
26     for(i=0; i<5; ++i)
27         printf("%d ",arr[i]);
28     printf("\n");
29     return 0;
30 }

  三、优化快排(浙大 数据结构)

  1、直接调用库函数

 1 /* 快速排序 - 直接调用库函数 */
 2  
 3 #include <stdlib.h>
 4  
 5 /*---------------简单整数排序--------------------*/
 6 int compare(const void *a, const void *b)
 7 { /* 比较两整数。非降序排列 */
 8     return (*(int*)a - *(int*)b);
 9 }
10 /* 调用接口 */ 
11 qsort(A, N, sizeof(int), compare);
12 /*---------------简单整数排序--------------------*/
13  
14  
15 /*--------------- 一般情况下,对结构体Node中的某键值key排序 ---------------*/
16 struct Node {
17     int key1, key2;
18 } A[MAXN];
19   
20 int compare2keys(const void *a, const void *b)
21 { /* 比较两种键值:按key1非升序排列;如果key1相等,则按key2非降序排列 */
22     int k;
23     if ( ((const struct Node*)a)->key1 < ((const struct Node*)b)->key1 )
24         k = 1;
25     else if ( ((const struct Node*)a)->key1 > ((const struct Node*)b)->key1 )
26         k = -1;
27     else { /* 如果key1相等 */
28         if ( ((const struct Node*)a)->key2 < ((const struct Node*)b)->key2 )
29             k = -1;
30         else
31             k = 1;
32     }
33     return k;
34 }
35 /* 调用接口 */ 
36 qsort(A, N, sizeof(struct Node), compare2keys);
37 /*--------------- 一般情况下,对结构体Node中的某键值key排序 ---------------*/

  2、快速排序(优化)

  24行代码为什么是,High = Right-1;  调用Median3函数后,返回的Pivot位于Right-1,因Right的值是大于Right-1的值的,比较的时候,High是先--再比较的,所以比较的是Right-2的值;

  Pivot的值一般定义为小于100的数;

 1 /* 快速排序 */
 2  
 3 ElementType Median3( ElementType A[], int Left, int Right )
 4 { 
 5     int Center = (Left+Right) / 2;
 6     if ( A[Left] > A[Center] )
 7         Swap( &A[Left], &A[Center] );
 8     if ( A[Left] > A[Right] )
 9         Swap( &A[Left], &A[Right] );
10     if ( A[Center] > A[Right] )
11         Swap( &A[Center], &A[Right] );
12     /* 此时A[Left] <= A[Center] <= A[Right] */
13     Swap( &A[Center], &A[Right-1] ); /* 将基准Pivot藏到右边*/
14     /* 只需要考虑A[Left+1] … A[Right-2] */
15     return  A[Right-1];  /* 返回基准Pivot */
16 }
17  
18 void Qsort( ElementType A[], int Left, int Right )
19 { /* 核心递归函数 */ 
20      int Pivot, Cutoff, Low, High;
21        
22      if ( Cutoff <= Right-Left ) { /* 如果序列元素充分多,进入快排 */
23           Pivot = Median3( A, Left, Right ); /* 选基准 */ 
24           Low = Left; High = Right-1; 
25           while (1) { /*将序列中比基准小的移到基准左边,大的移到右边*/
26                while ( A[++Low] < Pivot ) ;
27                while ( A[--High] > Pivot ) ;
28                if ( Low < High ) Swap( &A[Low], &A[High] );
29                else break;
30           }
31           Swap( &A[Low], &A[Right-1] );   /* 将基准换到正确的位置 */ 
32           Qsort( A, Left, Low-1 );    /* 递归解决左边 */ 
33           Qsort( A, Low+1, Right );   /* 递归解决右边 */  
34      }
35      else InsertionSort( A+Left, Right-Left+1 ); /* 元素太少,用简单排序 */ 
36 }
37  
38 void QuickSort( ElementType A[], int N )
39 { /* 统一接口 */
40      Qsort( A, 0, N-1 );
41 }
 1 #include <stdio.h>
 2 #define MAXN 50
 3 
 4 typedef int ElementType;
 5 void Swap(int*a, int*b)
 6 {
 7     int t = *a;
 8     *a = *b;
 9     *b = t;
10 }
11 
12 ElementType Qselect( ElementType A[], int K, int Left, int Right )
13 {
14     ElementType Pivot = A[Left];
15     int L = Left, R = Right+1;
16 
17     while (1) {
18         while (A[++L] < Pivot ) ;
19 
20         while (A[--R] > Pivot );
21 
22         if (L < R ) Swap( &A[L], &A[R] );
23         else break;
24     }
25 
26     Swap( &A[Left], &A[R] );
27     
28     /* printf("\nLeft=%d,L=%d,Right=%d,R=%d,K=%d,L-Left=%d,Pivot=%d\n",Left,L,Right,R,K,L-Left,Pivot); */
29 
30     if ( K < (L-Left) )
31         return Qselect(A, K, Left, R-1);
32     else if ( K > (L-Left) )
33         return Qselect(A, K-(L-Left), L, Right);
34     else
35         return Pivot;
36 }
37 
38 int quick_sort(int a[], int l, int r, int k)
39 {
40     int i,j;
41     i = l; j = r;
42     int x = a[l];
43     int t = a[l]; a[l] = a[r]; a[r] = t;
44     while (i < j)
45     {
46         while (i < j && a[i]<x) i++;
47         if (i < j)
48         {
49             a[j] = a[i];
50             j--;
51         }
52         while (i<j && a[j]>x) j--;
53         if (i < j)
54         {
55             a[i] = a[j];
56             i++;
57         }
58     }
59     a[i] = x;
60 
61     if (i - l + 1 == k)
62         return a[i];
63     else if (i - l + 1 < k)
64         return quick_sort(a, i + 1, r, k - (i - l + 1));
65     else return
66         quick_sort(a,l,i-1,k);
67 }
68 
69 int main()
70 {
71     int a[10] = {-1,2,3,0,5,6,7,8,9,10};//{10,9,8,7,6,5,4,3,2,1};// {1,2,3,4,5,6,7,8,9,10};//
72     for(int i=1; i<=10; ++i)
73       printf("%d ",Qselect(a,i,0,9));
74       /* printf("%d ",quick_sort(a,0,9,i)); */
75     printf("\n");
76     for(int i=0; i<=9; ++i)
77         printf("%d ",a[i]);
78     return 0;
79 }