《github一天一道算法题》:快速排序和随机快速排序

看书、思考、写代码!!!

/*********************************
 * [email protected]
 * blog: http://blog.csdn.net/hustyangju
 * 题目:快速排序和随机快速排序
 * 思路:采用分治+原址排序,分裂函数将区间分为三个子区间:<=主元、主元和>主元区间,再在主元旁边的两个子区间递归调用排序
 *      分裂函数一般将区间最后一个元素作为比较的主元,随机快排则随机选取区间内的一个元素交换到末尾作为主元
 * 空间复杂度:原址排序的空间复杂度可以视为0
 * 快排时间复杂度:最坏的情况下,即全部逆序,为0(n*n),期望时间复杂度为O(n lgn),实际情况下系数常量较小,效果较好
 * 随机快排时间复杂度:出现最坏的情况的可能性较低,数据量越大,时间复杂度越好于前一种快排,期望也为O(n lgn),实际情况下系数常量较小,效果较好
*/
#include <iostream>
#include <algorithm>

using namespace std;

class quick_sort_class
{
  public:
    quick_sort_class(int *a, int n):p_array(a), n_array(n){}//构造函数
    ~quick_sort_class();//析构函数
    void quick_sort(int i, int j);//快排接口
    void rand_quick_sort(int i, int j);//随机快排接口
    void print();//输出接口
  protected:
    int partition(int p, int r);//快排分裂函数,选取最后一个元素作为主元
    int rand_partition(int p, int r);//随机快排分裂函数,随机选取区间内的一个元素作为主元,移到最后一位
  private:
    int *p_array;
    int n_array;

};

quick_sort_class::~quick_sort_class()
{
}

//快排分裂函数,将区间元素分为:<=主元、主元和>主元 的三个区间,返回主元的位置
int quick_sort_class::partition(int p, int r)
{
    int x = p_array[r];
    int i = p-1;
    for(int j=p;j<r;++j)
    {
        if(p_array[j]<=x)
        {
            ++i;
            swap(p_array[i], p_array[j]);
        }
    }
    swap(p_array[i+1], p_array[r]);
    return i+1;
}

//随机快排的分裂函数,关键在于主元的选取,适合大量随机数的快速排序
int quick_sort_class::rand_partition(int p, int r)
{
    int a=p+rand()%(r-p+1);
    swap(p_array[a],p_array[r]);
    return partition(p,r);
}

//递归法、原址快速排序,采用3段分治策略,因为是原址,没有归并的必要
void quick_sort_class::quick_sort(int i, int j)
{
    if(i<j)
    {
        int q = partition(i, j);
        quick_sort(i, q-1);
        quick_sort(q+1, j);
    }
}

//递归法、原址快速排序,采用3段分治策略,因为是原址,没有归并的必要,调用随机分裂函数
void quick_sort_class::rand_quick_sort(int i, int j)
{
    if(i<j)
    {
        int q = rand_partition(i, j);
        quick_sort(i, q-1);
        quick_sort(q+1, j);
    }
}
//输出接口
void quick_sort_class::print()
{
    for(int i=0;i<n_array;++i)
        cout<<p_array[i]<<" ";
    cout<<endl;
}

int main()
{
    int array[10] = {8, 4, 7, 15, 10, 84, 23, 19, 3, 11};
    quick_sort_class myQuickSort(array, 10);
    cout<<"origin array:"<<endl;
    myQuickSort.print();
    cout<<"quick sort:"<<endl;
    myQuickSort.quick_sort(0, 9);
    myQuickSort.print();
    cout<<"******************"<<endl;
    int array1[10] = {8, 4, 7, 15, 10, 84, 23, 19, 3, 11};
    quick_sort_class myQuickSort1(array1, 10);
    cout<<"origin array:"<<endl;
    myQuickSort1.print();
    cout<<"rand quick sort:"<<endl;
    myQuickSort1.rand_quick_sort(0, 9);
    myQuickSort1.print();
}

测试结果:

时间: 2024-08-26 03:41:22

《github一天一道算法题》:快速排序和随机快速排序的相关文章

《github一天一道算法题》:搜索二叉树接口实现大合集

读书.思考.写代码! 说明: (1)这里实现了搜索二叉树的全部常用操作 (2)限于时间和精力,实现的较为粗糙,内存泄露.成员变量访问控制.返回类型.异常安全等没有照顾的到 (3)一切实现的手段都是贴近底层操作,关注原理.以后可能对推倒重来,实现一个完备的接口系统. /********************************************* * [email protected] * 题目:二叉树接口实现大合集 * 具体:二叉树的创建.插入.最大值.最小值.前中后序递归遍历与非递

《github一天一道算法题》:分治法求数组最大连续子序列和

看书.思考.写代码! /*************************************** * [email protected] * blog: http://blog.csdn.net/hustyangju * 题目:分治法求数组最大连续子序列和 * 思路:分解成子问题+合并答案 * 时间复杂度:O(n lgn) * 空间复杂度:O(1) ***************************************/ #include <iostream> using nam

《github一天一道算法题》:并归排序

看书.思考.写代码! /******************************************* * [email protected] * blog: http://blog.csdn.net/hustyangju * 2014-11-04 * 题目:并归排序 * 描述:中分法递归分解一个区间的数组,再合并子区间,在合并时完成排序 * 解题思路:递归法,利用临界条件层层合并 * 时间复杂度:O(n lgn) * 空间复杂度:O(n) * *********************

《github一天一道算法题》:插入排序

看书.思考.写代码! /*********************************************** * [email protected] * blog: http://blog.csdn.net/hustyangju * 2014-11-03 * 题目: 插入排序 * 描述: 给定一个数组,按照逐个插入比较的方法得到一个已序数组 * 解题思路:从第一个元素开始,在已序数组上插入下一个元素,可以从已序数组的尾部,也可以从头部逐个比较插入 * 时间复杂度:原数组顺序排好的情况下

《github一天一道算法题》:动态规划法解决最长公共子序列(LCS)问题的最简单方法

<pre name="code" class="cpp">/* * [email protected] * 问题:longest common subsequece problem * 思路:从底往上,利用动态规划,划分子问题,利用LCS子问题的长度变化,求得LCS * 时间复杂度O(m*n) * 空间复杂度O(m*n) */ #include <iostream> //#include <string> using namesp

《github一天一道算法题》:堆算法接口实现(堆排序、堆插入和堆取最值并删除)

看书.思考.写代码! /********************************************* * [email protected] * blog: http://blog.csdn.net/hustyangju * 题目:堆排序实现,另外实现接口:取堆最大值并删除.堆插入 * 思路:堆是在顺序数组原址上实现的,利用完全二叉树的性质,更具最大堆和最小堆的定义实现的. * 经典应用场景:内存中堆数据管理 * 空间复杂度:堆排序是在原址上实现的,为0 * 时间复杂度:堆排序为O

一天一道算法题---6.26---二分查找

感谢微信平台---一天一道算法题----每天多一点进步-- 好累啊  现在在用win7自带的输入法 打起来真麻烦 快点把这2天的搞完就重装了 还是直接来源于----〉 待字闺中 分析 给定一个数组A,其中有一个位置被称为Magic Index,含义是:如果i是Magic Index,则A[i] = i.假设A中的元素递增有序.且不重复,请给出方法,找到这个Magic Index.更进一步,当A中允许有重复的元素,该怎么办呢? 没有重复元素的情况 一些同学在遇到这个题目的时候,往往会觉得比较简单.

一天一道算法题--6.25--无定义

感谢微信平台---一天一道算法题--每天多一点进步---- 其实今天我接下去补上的几题都来自---待字闺中 所以我就原封不动的将它的题目与分析搬过来了 原题 给定一个数组,我们可以找到两个不相交的.并且是连续的子数组A和B,A中的数字和为sum(A), B中的元素和为sum(B).找到这样的A和B,满足sum(A) - sum(B)的绝对值是最大的. 例如:[2, -1 -2, 1, -4, 2, 8]划分为A=[-1, -2, 1, -4], B=[2, 8], 最大的值为16 分析 如果没有

一天一道算法题---6.27---二分图

感谢微信平台---一天一道算法题---每天多一点进步--- Ah... last... 也很晚了 快2点半了 C罗也告别这届世界杯了  主要还是输给德国太多球了 美国也没赢 唉 还是来源于----> 待字闺中 原题 大家都知道facebook用户都是双向的好友,a是b的好友,那么b一定是a的好友,现在给定一个用户列表,其中有些用户是好友,有些不是,请判断,这些用户是否可以划分为两组,并且每组内的用户,互相都不是好友.如果能,请给出这个划分. 例子1: 用户:{1, 2, 3} 好友关系:1-2,