数据结构-排序-桶排序

                            数据结构-排序-桶排序


先看下桶排序的基本思想

假定排序的值都在0~m-1之间,设置m个桶,依次把值为i的记录分配到第i个桶中,然后把个个桶的记录依次收集起来。

首先上下结构图

下标 key next
0 3(1) 1
1 5(1) 2
2 3(2) 3
3 1 4
4 5(2) 5
5 6 6
6 3(3) -1

这就是我们用静态链表存储待的排序记录,我们会让first指向下标为0的地方,只要next不为-1就接着遍历。

初始化代码如下

struct Node
{
    int key;
    int next;//记录下一个键值在数组中的下标
};
//传入参数Node r[],n  这里其实是默认了node数组里面key值已经存在
for(int i=0;i<n;i++)
{
    r[i].next=i+1;
}
r[n-1].next=-1;//设置最后一个的next为-1
first=0;

 


 

然后我们会传入某个值,比如这里最大的数为6,我们传个7或者8差不多偏大点的数字作为桶的个数。这里假设传m个

然后构造m个队列,为了存储以后相同的元素。

构造队列如下:

struct QueueNode//定义静态链队列存储桶
{
   int front;
   int rear;
};

//然后申明一组数组就行,m将是我们传入的参数
   QueueNode q[m];//初始化m个静态队列
    for(int i=0;i<m;i++)

q[i].front=q[i].rear=-1;

我们现在要把序列传入,然后分配

先放图   1图是待排序  2图是排序队列

下标 key next
0 3 1
1 2 2
2 3 -1

 

下标 front rear
0 -1  -1
1 -1 -1
2 1 1
3 0 2
4 -1 -1

 

遍历下标0的时候发现key=3,我们就去排序队列下标3的地方把front和rear都设为0,就相当于吧下标入队

然后遍历到下标2时候,发现key又=3我们就找到排序组的rear,这个rear的作用可以看作保存了上一次的入队的值在待排序组的下标

然后我门找到待排序组中这个数,怎么获取就是通过  ----- 待排序组【排序组【当前key值】.rear】里面的排序组【当前key值】.rear就是获取上次入队的下标。

然后我们只需要------待排序组【排序组【当前key值】.rear】=当前遍历下标就行了

排序后我们观察待排序图就是这样

下标 key next
0 3 2
1 2 -1
2 3 -1

注意这里的下标0的next就变成了2,下标2中正好是3

 

 

 

代码如下

//分配算法
void Distribute(Node r[],int n,QueueNode q[],m,int first)
{
    int i=first;//first为静态链表的头指针,从下标0开始存放待排序序列。
    while(r[i].next!=-1)//遍历待排序组
    {
        int k=r[i].key;         //获取key值
        if(q[k].front==-1)q[k].front=i;//处理队列为空,则把待排序的下标插入队列的front
        else r[q[k].rear].next=i;//假如改队列不为空就把待排序队列上个同值的next标记为下当前的i值
        q[k].rear=i;    //修改队尾指针
        i=r[i].next;    //i后移动,处理下一个记录
    }
}

接下来是收集操作就是把已经排序好的队列首位相连接

我们同样还是用上面那323的简单例子,一步步将

这是我们的原料,我们则么把队列都连起来呢?

首先我们看右边图,我们先找到不为空的序列,很简单判断front是不是-1就行了

然后遍历到2,找到front=1,发现next=-1说明没有下一个同样的值了,这时候我们已经遍历完一个队列,我们为了可以让这个队列的下一个可以接上,我们设个last保存当前下标

也就是1,然后我们接着遍历排序组,到了3,front!=-1,我们就把  ----待排序组[last].next=排序组[当前下标].front这样就首位相连了,然后再保存当前的rear的值到last继续下一个首尾相连

//收集算法
void collect(Node r[],int n,QueueNode q[],int m,int first)
{
    int k=0;
    while(q[k].front!=-1)//找非空队列
            k++;
    first=q[k].front;//获取第一个非空的排序组的front
    int last=q[k].rear; //获取第一个非空的排序组的rear
    while(k<m)//遍历排序组每一个队列
    {
        k++;      
        if(q[k].front!=-1)           //如果队列不为空
        {
            r[last].next=q[k].front;        //q[k].font是第一个入队的下标,也就是待排序中第一个出现这个值的下标
                                                                //r[last]是待排序中最后一个出现这个值的位置,把它的next指向第一个入队的下标
            last=q[k].rear;                         //q[k].rear的值表示待排序组中最后一次出现k值的下标
        }
    }
    r[last].next=-1;//待排序 最后一个设为-1
}

全部代码如下:

#include<iostream>
using namespace std;
struct Node
{
    int key;
    int next;//记录下一个键值在数组中的下标
};

struct QueueNode//定义静态链队列存储桶
{
   int front;
   int rear;
};
//分配算法
void Distribute(Node r[],int n,QueueNode q[],int m,int first)
{
    int i=first;//first为静态链表的头指针,从下标0开始存放待排序序列。
    while(r[i].next!=-1)//遍历待排序组
    {
        int k=r[i].key;         //获取key值
        if(q[k].front==-1)q[k].front=i;//处理队列为空,则把待排序的下标插入队列的front
        else r[q[k].rear].next=i;//假如改队列不为空就把待排序队列上个同值的next标记为下当前的i值
        q[k].rear=i;    //修改队尾指针
        i=r[i].next;    //i后移动,处理下一个记录
    }
}
//收集算法
void collect(Node r[],int n,QueueNode q[],int m,int first)
{
    int k=0;
    while(q[k].front!=-1)//找非空队列
            k++;
    first=q[k].front;//获取第一个非空的排序组的front
    int last=q[k].rear; //获取第一个非空的排序组的rear
    while(k<m)//遍历排序组每一个队列
    {
        k++;      
        if(q[k].front!=-1)           //如果队列不为空
        {
            r[last].next=q[k].front;        //q[k].font是第一个入队的下标,也就是待排序中第一个出现这个值的下标
                                                                //r[last]是待排序中最后一个出现这个值的位置,把它的next指向第一个入队的下标
            last=q[k].rear;                         //q[k].rear的值表示待排序组中最后一次出现k值的下标
        }
    }
    r[last].next=-1;//待排序 最后一个设为-1
}

//桶排序算法
void BucketSocket(Node r[],int n, int m)
{
    for(int i=0;i<n;i++)    //初始化静态链表
        r[i].next=i+1;
    r[n-1].next=-1;
    int first=0;
    QueueNode q[m];//初始化m个静态队列
    for(int i=0;i<m;i++)
        q[i].front=q[i].rear=-1;
    Distribute(r,n,q,m,first);      //分配
    collect(r,n,q,m,first);             //收集
    
}

 

 

 

 

原文地址:https://www.cnblogs.com/DJC-BLOG/p/9096390.html