zoukankan      html  css  js  c++  java
  • 算法(第四版)学习笔记(三)——快速排序

    快速排序

    步骤:(升序) 可在排序前将数组打乱

    设a[lo]为切分元素temp(temp=a[lo]),将数组分为三部分:

    • 不大于切分元素的小数组A
    • A小数组与B小数组间插入temp
    • 不小于切分元素的小数组B

    如何切分:

    设立一个从左到右扫描的指针i直到找大于等于切分元素的元素,同时一个从右到左的扫描指针j直到找小于等于切分元素的元素

    两元素交换位置,继续扫描直到i>=j(A、B小数组已经排完整)时停止扫描。

     1 #include<stdio.h>
     2 #include<malloc.h>
     3 int sort(int *a,int lo,int hi);
     4 int less(int a,int b);
     5 void each(int *a,int *b);
     6 int partition(int *a,int lo,int hi);
     7 int main()
     8 {
     9     int n,i;
    10     scanf("%d",&n);
    11     int *a=(int *)malloc(sizeof(int)*n);
    12     for(i=0;i<n;i++)
    13     scanf("%d",&a[i]);
    14     sort(a,0,n-1);
    15     for(i=0;i<n;i++)
    16     printf("%d ",a[i]);
    17     return 0;
    18 }
    19 int sort(int *a,int lo,int hi)
    20 {
    21     if(lo>=hi)
    22     return 0;
    23     int j=partition(a,lo,hi);
    24     sort(a,lo,j-1);
    25     sort(a,j+1,hi);
    26 }
    27 int partition(int *a,int lo,int hi)
    28 {
    29     int i,j,temp;
    30     temp=a[lo];
    31     i=lo;
    32     j=hi+1;
    33     
    34     while(1)
    35     {
    36         while(less(a[++i],temp))  
    37             if (i==hi) //a[hi]大等于temp 
    38                 break;
    39         while(less(temp,a[--j]))
    40             if(j==lo)
    41                 break;
    42         if(i>=j)//两个小数组已分好 
    43         break;
    44         each(&a[i],&a[j]);
    45     }
    46     each(&a[j],&a[lo]);//temp放到两小数组中间 
    47     return j;
    48 }
    49 int less(int a,int b)
    50 {
    51     if(a<b) 
    52     return 1;
    53     return 0;
    54 }
    55 void each(int *a,int *b)
    56 {
    57     int temp;
    58     temp=*a;
    59     *a=*b;
    60     *b=temp; 
    61 }

    疑问:为什么返回 j,而不是i?切分元素是和a[j]交换,而不是a[i]?

    答:切分数组占据的位置是小数组A的位置(小数组存储的是不大于切分元素的元素 ),而指针j在结束时指向的元素刚好是小数组A的最后一位元素。

    改进后: 

    三向切分快速排序

    设a[lo]为切分元素temp(temp=a[lo]),将待切分的数组分为四部分:

    • a[lo]~a[lt-1]为小于切分元素的小数组
    • a[lt]~a[i-1]为等于切分元素的小数组
    • a[i]~a[gt]为待与切分元素比较的小数组
    • a[gt+1]为大于切分元素的小数组
     1 #include<stdio.h>
     2 #include<malloc.h>
     3 int sort(int *a,int lo,int hi);
     4 int less(int a,int b);
     5 void each(int *a,int *b); 7 int main()
     8 {
     9     int n,i;
    10     scanf("%d",&n);
    11     int *a=(int *)malloc(sizeof(int)*n);
    12     for(i=0;i<n;i++)
    13     scanf("%d",&a[i]);
    14     sort(a,0,n-1);
    15     for(i=0;i<n;i++)
    16     printf("%d ",a[i]);
    17     return 0;
    18 }
    19 int sort(int *a,int lo,int hi)
    20 {
    21     int lt,gt,i,j,temp;
    22     if(lo>=hi)
    23     return 0;
    24     temp=a[lo];
    25     i=lo+1;
    26     lt=lo;
    27     gt=hi;
    28     while(i<=gt)
    29     {
    30         if(a[i]<temp)
    31         each(&a[lt++],&a[i++]);//保证a[lt]到a[i-1]等于v 
    32         else if(a[i]>temp)
    33         each(&a[gt--],&a[i]);//交换后再判断原a[gt]值的大小 
    34         else 
    35         i++;
    36     }
    37     sort(a,lo,lt-1);
    38     sort(a,gt+1,hi);
    39 }
    40 int less(int a,int b)
    41 {
    42     if(a<b) 
    43     return 1;
    44     return 0;
    45 }
    46 void each(int *a,int *b)
    47 {
    48     int temp;
    49     temp=*a;
    50     *a=*b;
    51     *b=temp; 
    52 }

     优势:  

      避免了与切分元素相同的元素参与到下一环节的递归运算,效率更高。

      当存在主键重复时,三向切分比归并排序快。

  • 相关阅读:
    nfs只能挂载为nobody的解决方法
    Mysql一些记忆
    shell中交互输入自动化
    关闭SElinux
    《Windows核心编程系列》十谈谈同步设备IO与异步设备IO之异步IO
    《Windows核心编程系列》九谈谈同步设备IO与异步设备IO之同步设备IO
    《Windows核心编程系列》八谈谈用内核对象进行线程同步
    《windows核心编程系列》七谈谈用户模式下的线程同步
    《windows核心编程系列 》六谈谈线程调度、优先级和关联性
    《windows核心编程系列》五谈谈线程基础
  • 原文地址:https://www.cnblogs.com/myanswer/p/7351848.html
Copyright © 2011-2022 走看看