#include <iostream>
#include <ctime>
#include <cstdlib>
#include <algorithm>
#include <iterator>
#include <cassert>

using namespace std;

template<class T>
struct LinkNode
{
   LinkNode() = default;
   LinkNode(const T& t):m_data(t){}
   T m_data{0};
   LinkNode<T>* m_next{nullptr};
};

template<class T>
class LinkList
{
public:
    LinkList();
    ~LinkList();
    int length() const;
    void append(const T& t);
    void merge(const LinkList<T>& list);
    void show() const;
    void clear();
public:
    LinkNode<T> *m_head{nullptr};
};

template<class T>
LinkList<T>::LinkList()
{
    m_head = new LinkNode<T>();
}

template<class T>
LinkList<T>::~LinkList()
{
    LinkNode<T> *n{nullptr};
    while(m_head)
    {
        n = m_head;
        m_head = m_head->m_next;
        delete n;
    }
    m_head = nullptr;
}

template<class T>
void LinkList<T>::clear()
{
    LinkNode<T>* t = m_head->m_next,*t1{nullptr};
    while(t)
    {
       t1 = t;
       t = t->m_next; 
       delete t1;
    }
    m_head->m_next = nullptr;
}

template<class T>
void LinkList<T>::append(const T& v)
{
    LinkNode<T> *t = m_head;
    while(t && t->m_next)
    {
        t = t->m_next;
    }

    t->m_next = new LinkNode<T>(v);
}

template<class T>
int LinkList<T>::length() const
{
    LinkNode<T> *t = m_head->m_next;
    int n{0};
    while(t)
    {
        n++;
        t = t->m_next;
    }
    return n;
}

template<class T>
void LinkList<T>::show() const
{
   LinkNode<T> *t = m_head->m_next;
   while(t)
   {
       cout<<t->m_data<<","; 
       t = t->m_next;
   }
   cout<<endl;
}

template<class T>
void LinkList<T>::merge(const LinkList<T>& list)
{
    LinkNode<T> *t = list.m_head->m_next;
    while(t)
    {
        append(t->m_data);
        t = t->m_next;
    }
}

//===================================
class Bucket
{
public:
    int length() const { return m_list.length();}
    void setKey(int key){ m_key = key;}
    int key() const { return m_key;}
    void append(int n);
    void clear();
    void merge(const Bucket& b);
    void show() const;
    void copyToArray(int *array,int pos);
private:
    int m_key;
    LinkList<int> m_list;
};

void Bucket::copyToArray(int *array,int pos)
{
   LinkNode<int> *t = m_list.m_head->m_next;
   int k{0};
   while(t)
   {
        array[pos+k] = t->m_data;
        ++k;
        t = t->m_next;
   } 
}

void Bucket::append(int n)
{
    m_list.append(n);
    cout<<"["<<m_key<<"]"<<"桶里面现在有"<<m_list.length()<<" 个"<<endl;
}

void Bucket::clear()
{
    m_list.clear();
}

void Bucket::merge(const Bucket& b)
{
    m_list.merge(b.m_list);
}

void Bucket::show() const
{
    m_list.show();
}   

//================================================
void max_min(int *arr,int n,int &max,int &min)
{
    int minIndex{0},maxIndex{0};
    for(int i=1; i<n; ++i)
    {
        if(arr[minIndex] > arr[i])
            minIndex=i;
        if(arr[maxIndex] < arr[i])
            maxIndex=i;
    }

    max = arr[maxIndex];
    min = arr[minIndex];
}

/*!
桶排序的原则和排序扑克牌是一样的,
首先需要确定数据的范围,然后根据数据的范围
将所有的数据串起来,适合数据范围小的排序
1->9
10->J
11->Q
12->K
13->King
*/

void dumpPoker(int *arr,int & length)
{
    copy(arr,arr+length,ostream_iterator<int>(cout,","));
    cout<<endl;
}

void initPoker(int *&arr,int& length)
{
    length = 54;
    arr = new int[length];
    int k=0;
    for(int i=0; i<4; ++i)
        for(int j=0; j<13;j++)
            arr[k++] = j;
    arr[length-1]=arr[length-2] = 13;
    random_shuffle(arr,arr+length);
}

void checkPoker(int *arr,int length)
{
    for(int i=1; i<length; ++i)
    {
        if(arr[i-1] > arr[i])
        {
            cout<<"扑克牌无序"<<endl;
            assert(false);
            break;
        }
    }
}

void free(int *arr)
{
    delete []arr;
}

void bucket_sort(int *arr,int length)
{
    int min{0},max{0};
    max_min(arr,length,max,min);    
    int bucket_count{max-min+1};
    Bucket *brr = new Bucket[bucket_count];
    for(int i=min; i<=max;++i)
    {
        brr[i-min].setKey(i);
    }
    
    /*!
    将对应的数据放置到木桶中
    */
    for(int i=0; i<length; ++i)
    {
        brr[arr[i]-min].append(arr[i]);
    }

    Bucket r;
    for(int i=min; i<=max;++i)
    {
        r.merge(brr[i-min]);
    }

    r.show();
    
    /*!将木桶中的结果拷贝回去*/
    int pos{0},bucketcount{0};
    for(int i=0; i<bucket_count; ++i)
    {
        bucketcount = brr[i].length();
        if(bucketcount > 0)
        {
            brr[i].copyToArray(arr,pos);
            pos += bucketcount;
        }
    }
    
    cout<<"pos="<<pos<<" length="<<length<<endl;
    assert(pos == length);
    delete[] brr;
}


int main(int argc,char *argv[])
{
    int *poker{nullptr};
    int length{0};
    initPoker(poker,length);

    cout<<"原始数据"<<endl;
    dumpPoker(poker,length);
    bucket_sort(poker,length);
    cout<<"排序后"<<endl;
    dumpPoker(poker,length);
    checkPoker(poker,length);
    
    free(poker);
    return 0;
}

木桶排序-扑克牌的更多相关文章

  1. 在Xcode中,有没有办法对方法的下拉列表进行排序

    在Xcode中,有一个首选项可以按字母顺序对“编辑器函数”弹出窗口进行排序,这很棒.但是,这并未考虑同样出现在此列表中的#pragma标记标题.将这个列表首先按字母顺序排序,然后按#pragmaheading,然后按方法排序会很棒.这可能吗?

  2. Swift-ReactiveCocoa3.0二SignalProducer 2

    lift运算符|>内部也是调用了lift方法,作用是把原producer的结果transform完返回新的类型/值,再封装成新的producer返回。只有在第一个producer销毁后才会响应第二个producer。之后,每当其中一个再sendNext,都会在next回调zipwith压缩两个信号,每当两个都sendNext一次才回在next回调一次。例子:sampleOn采样,当sampleOn的信号sendNext一次,就取一次producer1的最新一次sendNext的值进行next回调takeu

  3. 如何在Swift中调用C函数

    “,选择Yes,创建SwiftCallC-Bridging-Header.h文件给工程建立一个C语言文件。跟上述步骤3类似,只不过这里选择的是C文件,这里的文件取名为CFile.c,同时自动生成CFile.h文件开始编写代码。在SwiftCallC-Bridging-Header.h文件中声明C函数,这里是voidcallCDemo()在CFile.c中定义这个函数在main.swift中调用这个C函数编译运行

  4. Swift--UINavigationController

    代码目录AppDelegate.swiftViewController.swiftNext.swift效果图

  5. Swift如何取得View所属的ViewController

    从VC取得View很容易,但有些情况下我们需要从View反向获取VC.不过在一些特殊的场合,Cocoa库帮我们想的很周到,比如在自定义view过渡动画的时候:系统在回调我们的animateTransition方法时,会传入一个context参数,从它我们可以轻松取得参与动画的toView,fromView以及它们对应的VC:但不是所有情况系统都会帮你考虑的这么周到,所以有时候还得需要自己从View

  6. RxSwift使用教程大全 韩俊强的博客

    记录大多数ReactiveX的概念和操作符。我们还需要使用KVO来检测变量的值改变。Rx就是为解决这些问题而生的。Observable理解RxSwift的关键是理解Observable的概念。使用variable的好处是variable将不会显式的发送Error或者Completed。

  7. Swift - 选择排序算法

    思想每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。步骤找到第一小(大)的元素,放在第一个位置找到从第二个元素到末尾的元素中第二下(大)的元素,放入第二个位置以此类推代码结果特性时间复杂度:O(n^2)==n的平方稳定性:不稳定其他新blog地址www.livefor.cn

  8. swift – 全局函数序列(state:next :)和类型推断

    3,让seq2=4…

  9. 数组 – 封闭平面嵌套对象?

    我开始学习闭包,并希望在我正在开发的项目中实现它们,我想要一些帮助.我有一个类定义如下:我想使用闭包或更高级的函数来展平[MyObject]并将所有MyObject和subOjects连接成一个数组.我尝试使用[MyObject].flatMap(),但此操作不返回嵌套的子对象.展平递归类结构的一种方法是使用递归函数.这是我们想要展平的课程:以下是演示如何完成此操作的函数:这种方法的核心是recursiveFlat本地函数.它将嵌套对象的内容附加到结果中,然后有条件地为每个元素调用自身以添加其内容.

  10. android – 如何对CursorLoader结果进行排序?

    我使用CursorLoader查询结果,这不是我想要在ListFramgenet中显示的顺序.怎么排序呢?我用它来设置适配器:创建加载器:嗯,查询结果有纬度和经度.我想计算我的位置和这些结果之间的距离.并按距离asc排序.怎么排序呢?任何答案都会被批评解决方法这实际上非常简单:由此:对此:请记住,如果您的提供商中有一些方法可以检查投射并引发异常,您必须在进行测试时将其注释掉,或者将新列添加到官方投影数组中.

随机推荐

  1. crontab发送一个月份的电子邮件

    ubuntu14.04邮件服务器:Postfixroot收到来自crontab的十几封电子邮件.这些邮件包含PHP警告.>我已经解决了这些警告的原因.>我已修复每个cronjobs不发送电子邮件(输出发送到>/dev/null2>&1)>我删除了之前的所有电子邮件/var/mail/root/var/spool/mail/root但我仍然每小时收到十几封电子邮件.这些电子邮件来自cronjobs,

  2. 模拟两个ubuntu服务器计算机之间的慢速连接

    我想模拟以下场景:假设我有4台ubuntu服务器机器A,B,C和D.我想在机器A和机器C之间减少20%的网络带宽,在A和B之间减少10%.使用网络模拟/限制工具来做到这一点?

  3. ubuntu-12.04 – 如何在ubuntu 12.04中卸载从源安装的redis?

    我从源代码在Ubuntu12.04上安装了redis-server.但在某些时候它无法完全安装,最后一次makeinstallcmd失败.然后我刚刚通过apt包安装.现在我很困惑哪个安装正在运行哪个conf文件?实际上我想卸载/删除通过源安装的所有内容,只是想安装一个包.转到源代码树并尝试以下命令:如果这不起作用,您可以列出软件自行安装所需的步骤:

  4. ubuntu – “apt-get source”无法找到包但“apt-get install”和“apt-get cache”可以找到它

    我正在尝试下载软件包的源代码,但是当我运行时它无法找到.但是当我运行apt-cache搜索squid3时,它会找到它.它也适用于apt-getinstallsquid3.我使用的是Ubuntu11.04服务器,这是我的/etc/apt/sources.list我已经多次更新了.我尝试了很多不同的debs,并没有发现任何其他地方的错误.这里的问题是你的二进制包(deb)与你的源包(deb-src)不

  5. ubuntu – 有没有办法检测nginx何时完成正常关闭?

    &&touchrestarted),因为即使Nginx没有完成其关闭,touch命令也会立即执行.有没有好办法呢?这样的事情怎么样?因此,pgrep将查找任何Nginx进程,而while循环将让它坐在那里直到它们全部消失.你可以改变一些有用的东西,比如睡1;/etc/init.d/Nginx停止,以便它会休眠一秒钟,然后尝试使用init.d脚本停止Nginx.你也可以在某处放置一个计数器,这样你就可以在需要太长时间时发出轰击信号.

  6. ubuntu – 如何将所有外发电子邮件从postfix重定向到单个地址进行测试

    我正在为基于Web的应用程序设置测试服务器,该应用程序发送一些电子邮件通知.有时候测试是使用真实的客户数据进行的,因此我需要保证服务器在我们测试时无法向真实客户发送电子邮件.我想要的是配置postfix,以便它接收任何外发电子邮件并将其重定向到一个电子邮件地址,而不是传递到真正的目的地.我正在运行ubuntu服务器9.10.先感谢您设置本地用户以接收所有被困邮件:你需要在main.cf中添加:然后

  7. ubuntu – vagrant无法连接到虚拟框

    当我使用基本的Vagrantfile,只配置了两条线:我看到我的虚拟框打开,但是我的流氓日志多次显示此行直到超时:然后,超时后的一段时间,虚拟框框终于要求我登录,但是太久了!所以我用流氓/流氓记录.然后在我的物理机器上,如果我“流氓ssh”.没有事情发生,直到:怎么了?

  8. ubuntu – Nginx – 转发HTTP AUTH – 用户?

    我和Nginx和Jenkins有些麻烦.我尝试使用Nginx作为Jenkins实例的反向代理,使用HTTP基本身份验证.它到目前为止工作,但我不知道如何传递带有AUTH用户名的标头?}尝试将此指令添加到您的位置块

  9. Debian / Ubuntu – 删除后如何恢复/ var / cache / apt结构?

    我在ubuntu服务器上的空间不足,所以我做了这个命令以节省空间但是现在在尝试使用apt时,我会收到以下错误:等等显然我删除了一些目录结构.有没有办法做apt-getrebuild-var-tree或类似的?

  10. 检查ubuntu上安装的rubygems版本?

    如何查看我的ubuntu盒子上安装的rubygems版本?只是一个想法,列出已安装的软件包和grep为ruby或宝石或其他:)dpkg–get-selections

返回
顶部