zoukankan      html  css  js  c++  java
  • 快速排序

    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    #define N 10
    void swap(int *,int *);
    void qsort(int *,int,int);
    void init(int *);
    void show(int *);
    int main()
    {
            int arr[N]={0};
            init(arr);
            show(arr);
            qsort(arr,0,N-1);
            show(arr);
            system("pause");
    }
    void swap(int *a,int *b)
    {
            int tmp;
            tmp = *a;
            *a = *b;
            *b = tmp;
    }
    void init(int *arr)
    {
            int i;
            srand( time(NULL) );
            for(i=0;i<N;i++)
            {
                    arr[i]=rand()%100;
            }
    }
    void show(int *arr)
    {
            int i;
            for(i=0;i<N;i++)
            {
                    printf("%4d",arr[i]);
                    if(i!=0&&(i+1)%20==0)        { printf(" "); }
            }
            printf(" ");
    }
    void qsort(int *arr,int left,int right)
    {
            int qleft = left , qright = right;
            int pivot=arr[qleft];
            //if( qleft<=qright ) // 这样写也可以,就是不能用while,不然一直循环了
            while( qleft<qright )
            {
                    while( qleft!=qright )
                    {
                            while( qleft<qright && arr[qright]>=pivot )
                                    qright--;
                            arr[qleft] = arr[qright];
                            while( qleft<qright && arr[qleft]<=pivot )
                                    qleft++;
                            arr[qright] = arr[qleft];
                    }
                    arr[qleft] = pivot;  //基准放在最终位置
                    qsort(arr,left,qleft-1);
                    qsort(arr,qright+1,right);
            }
    }


    void qsort(int *arr,int _left,int _right)
    {
            int left=_left,right=_right,current=_left;
            int pivot=arr[_left];
            if( left<right )
            {
                    current++;
                    while( current<=right )
                    {
                            if( arr[current]<=pivot )
                            {
                                    swap(&arr[left],&arr[current]);
                                    left++;
                                    current++;
                            }//循环到最后,left就是基准的最终位置。arr[left]的值永远等于基准,left和current紧挨在一起
                            else
                            {
                                    swap(&arr[current],&arr[right]);
                                    right--;
                            }
                    }
                    qsort(arr,_left,left-1);
                    qsort(arr,right+1,_right);
            }
    }



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


    // 递归调用函数要注意递归出口,没有IF,这里会一直执行到qsort

    //考虑算法的时候要多想想边界条件和极端条件,还有出循环的条件。

    // 这个改进也不用想这么复杂,和正常的快速排序一样,left永远指向下一个要交换的左边元素,current指向当前要比较的元素,right指向最右边要比较交换的元素。最终确定一个元素,由current指向;这时候还要对0~left-1的元素快排,还有right+1~end的元素快排。


    // 模拟测试数据{2,1,3,2,3}和{3,1,2,3,2}



    void qsort1(int *arr ,int _left,int _right)
    {
            int left = _left,right = _right,current=_left;
            int pivot = arr[left];
            if(left<right)
            {
                    while(current<=right)  // 为什么要有=,可以考虑下最简单的只有两个元素{2,1},else if 和 if 开始循环的头两次都要执行到
                    {
                            if( arr[current]<pivot )
                            {
                                    swap(&arr[left],&arr[current]);  // 初始第一次进入循环会执行current++,然后第二次执行会执行交换,所以left永远指向的值都等于基准。
                                    left++;
                                    current++;
                            }
                            else if( arr[current]==pivot ) // 如果和基准元素一样就直接偏移寻找下一个元素比较,这样到最后left-1和它左边的就都是小于基准的,right+1和它右边的就都是大于基准的
    // left 和 current 之间的就都是和基准一样的值
                            {
                                    current++;
                            }
                            else
                            {
                                    swap(&arr[current],&arr[right]);
                                    right--;
                            }
                    }
                    qsort1(arr,_left,left-1);  // 这里left减不减1都一样正确。
                    qsort1(arr,right+1,_right);  // 试想特殊情况,数组有序,最后都会执行else造成right--,所以这里如果不right+1这里就会死循环出不去
    // eg:{1,2},执行while,countz++==1,right--==0,退出循环,到这里又变成0,1。
    // 最后跳出 while 循环的条件是current>right,current前的都是排好序的,所以后面right+1
    // 循环最后都是right在current的后面一个位置
            }
    }



    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    #define N 9
    void swap(int *,int *);
    void show(int *);
    int find_once(int *,int,int);
    int find_once_quick(int *);
    // 两组测试数据,方便模拟程序
    // {2,1,3,3,2}; {3,1,2,3,2}
    void find_doubleOnce(int *,int,int);
    // 测试数据
    // {0,9,9,3,0,1};
    void find_threeOnce(int *,int,int);
    int main()
    {
            int arr[N]={0,9,9,3,0,1,2,1,4};
            int result;
            //init(arr);
            show(arr);
            //result = find_once(arr,0,N-1);
            //result = find_once_quick(arr);
            //printf("%d ",result);
            //find_doubleOnce(arr,0,N-1);
            find_threeOnce(arr,0,N-1);
            printf(" ");
            show(arr);
            system("pause");
    }
    void swap(int *a,int *b)
    {
            int tmp;
            tmp = *a;
            *a = *b;
            *b = tmp;
    }
    void show(int *arr)
    {
            int i;
            for(i=0;i<N;i++)
            {
                    printf("%4d",arr[i]);
                    if(i!=0&&(i+1)%20==0)        { printf(" "); }
            }
            printf(" ");
    }
    //有101个整数,其中有50个数出现了两次,1个数出现了一次, 找出出现了一次的那个数.
    int find_once(int *arr,int _left,int _right)
    {
            int left=_left,right=_right,current=_left;
            int pivot=arr[_left];
            while(current<=right)
            {
                    if( arr[current]<pivot )
                    {
                            swap(&arr[left],&arr[current]);
                            left++;
                            current++;
                    }
                    else if( arr[current]==pivot )
                    {
                            current++;
                    }
                    else
                    {
                            swap(&arr[current],&arr[right]);
                            right--;
                    }
            }
            if(left==right)        // 本来left和current之间的都是基准元素的值,跳出while循环的时候,right==current-1,都是两两相同的数,如果left==right,说明就是要找的只出现一次的数。
            {
                    return arr[left];
            }
            else if( (left%2)==1 )        // 唯一的一个出现一次的数在左边
            {
                    find_once(arr,_left,left-1);
            }
            else if(((_right-right)%2)==1)
            {
                    find_once(arr,right+1,_right);
            }
    }
    int find_once_quick(int *arr)
    {
            int result=0;
            int i;
            for(i=0;i<N;i++)
            {
                    result = result^arr[i];
            }
            return result;
    }

    // 有102个整数,其中有50个数出现了两次,2个数出现了一次, 找出出现了一次的那2个数.
    void find_doubleOnce(int *arr,int _left,int _right)
    {
            int left=_left,right=_right,current=left;
            int pivot=arr[left];
            if( _left<=_right )
            {
                    while(current<=right)
                    {
                            if( arr[current]<pivot )
                            {
                                    swap(&arr[left],&arr[current]);
                                    left++;
                                    current++;
                            }
                            else if( arr[current]==pivot )
                            {
                                    current++;
                            }
                            else
                            {
                                    swap(&arr[right],&arr[current]);
                                    right--;
                            }
                    }
                    if( left==right )
                    {
                            printf("%3d ",arr[left]);
                            if( left%2==1 )
                            {
                                    find_doubleOnce(arr,_left,left-1);
                            }
                            else
                            {
                                    find_doubleOnce(arr,right+1,_right);
                            }
                    }
                    else
                    {
                            find_doubleOnce(arr,_left,left-1);
                            find_doubleOnce(arr,right+1,_right);
                    }
            }
    }
    // 有103个整数,其中有50个数出现了两次,3个数出现了一次, 找出出现了一次的那3个数.
    void find_threeOnce(int *arr,int _left,int _right)
    {
            int left=_left,right=_right,current=_left;
            int pivot=arr[_left];
            if(left<=right)
            {
                    while(current<=right)
                    {
                            if( arr[current]<pivot )
                            {
                                    swap(&arr[current],&arr[left]);
                                    left++;
                                    current++;
                            }
                            else if( arr[current]==pivot ) 
                            {
                                    current++;
                            }
                            else
                            {
                                    swap(&arr[current],&arr[right]);
                                    right--;
                            }
                    }
                    if( left==right )
                    {
                            printf("%3d ",arr[left]);
                    }
                    find_threeOnce(arr,_left,left-1);
                    find_threeOnce(arr,right+1,_right);
            }
    }
    //这三个问题都是一类的,之所以能这样做是因为从都的数都是两两出现,left和current只有两种情况:
    //第一种就是第一个元素出现两次,那么这时候left和current之间就都是这个数。最后right==current,所以它们两个数之间相差1,不可能相等
    //第二种情况就是第一个数只出现一次,这样最后left==right

  • 相关阅读:
    关于使用gitlab协同开发提交代码步骤
    一些JavaScript中原理的简单实现
    关于JavaScript中bind、applay、call的区别
    在腾讯云centos7.2上安装配置Node.js记录
    JAVA Web期末项目第三阶段成果
    在腾讯云服务器上安装JDK+Tomcat并启动tomcat
    《JavaScript算法》二分查找的思路与代码实现
    将本地的一个项目托管到自己的GitHub仓库
    《JavaScript算法》常见排序算法思路与代码实现
    项目经理建议:管理时间等于管理自己
  • 原文地址:https://www.cnblogs.com/meihao1203/p/8023480.html
Copyright © 2011-2022 走看看