基数排序,图解

基数排序其实是利用队列先进先出的特点,然后进行排序的。基本方法是这样:
int arr[] = {278,109,63,930,589,184,505,269,8,83};
1.初始化十个(数组元素的个数)队列bucket,并存放在一个数组中;
2.求base,即数组中最大元素是几位数。在这个数组中,base = 3;
3.接下来就要入队列了,这是很关键的一步。首先你要决定以什么样的方式入队列,怎么入,其次你要考虑入到哪里。基于base,我们先求出来元素的最后一位数,然后将求出来的数作为bucket的下标,也就是将该元素放到所对应的队列中。举个例子来说,对于数字278,base走第一次循环求出来的数是8,所以它就应该存放在bucket[8]中。然后按照这种方法,我们把十个数都放到各自对应的队列中。

这里写图片描述
4.现在十个数都被放倒对应的队列中了,下来就该出队列了。出队列好说。arr下标从0开始走,同时判断队列是否为空,不为空的话出队列,并将其数据存放在arr中,直到所有元素全部出完。这个时候你会看到数组中元素的最后一位是按照顺序排列的。
5.接下来求出元素的倒数第二位数,然后像第二步一样,给它入队列。还是拿278来说,它应该被放到bucket[7]中。
这里写图片描述
6.十个元素都被放到队列中了,接下来又该出队列了,让那些元素回到它们母亲的怀抱了,像第四步那样做就可以了。
这里写图片描述
8.就剩最后一步了,将所有的元素都放回去就大功告成了。当然,这是基于base等于3的情况,如果base更大,那肯定循环的次数就更多了。
下面来看看代码的实现吧:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>

//初始化一个队列
LINK_SORT *init_queue()   
{
    LINK_SORT *p = (LINK_SORT *)malloc(sizeof(LINK_SORT));
    assert(p != NULL);
    p->data = 0;
    p->next = NULL;
    return p;
}
//销毁队列
bool destory_queue(LINK_SORT *phead)  
{
    if (phead == NULL)
    {
        return false;
    }

    LINK_SORT *p = phead->next;
    //释放队列中的元素
    while (p != NULL)
    {
        phead->next = p->next;
        free(p);
        p = phead->next;
    }

    free(phead);     //释放头结点
    return true;
}

//申请一个结点
static LINK_SORT *alloc_node(elem_type e)
{
    LINK_SORT *tmp = (LINK_SORT *)malloc(sizeof(LINK_SORT));
    assert(tmp != NULL);

    tmp->data = e;
    tmp->next = NULL;

    return tmp;
}

//判断队列是否为空
bool is_empty(LINK_SORT *phead)
{
    if (phead == NULL)
    {
        return false;
    }
    return phead->next == NULL;
}

//查看队列中的第一个元素,只是查看,并不出队列
bool get_head(LINK_SORT *phead, elem_type *e)
{
    if (phead == NULL)
    {
        return false;
    }
    *e = phead->next->data;
    return true;
}

//入队列
bool push(LINK_SORT *phead, elem_type e)
{
    if (phead == NULL)
    {
        return false;
    }

    LINK_SORT *p = phead;
    LINK_SORT *tmp = alloc_node(e);
    while(p->next != NULL)
    {
        p = p->next;
    }

    p->next = tmp;

    return true;

}

//出队列
bool pop(LINK_SORT *phead, elem_type *e)
{
    if (phead == NULL || is_empty(phead))
    {
        return false;
    }

    LINK_SORT *p = phead->next;

    phead->next = p->next;
    *e = p->data;
    free(p);
    return true;
}

//计算数组中最大元素的位数
int get_base(int *arr,int len)
{
    int max = arr[0];
    //求数组中的最大元素
    for (int i=1;i<len;i++)
    {
        if (max < arr[i])
        {
            max = arr[i];
        }
    }
    int count = 0;

    // 计算最大元素的位数
    while(max != 0)
    {
        max /= 10;
        count++;
    }
    return count;
}

//排序
void base_sort(int *arr, int len, int base,int radix)
{
    LINK_SORT **bucket = (LINK_SORT **)malloc(sizeof(LINK_SORT *) * radix);//二级指针用来保存队列的地址
    assert(bucket != NULL);

    for (int i = 0;i<len;i++)
    {
        bucket[i] = init_queue();//以待排序数组的长度为标准初始化队列
    }

    for (int i = 0;i<base;i++)//遍历每个元素的每一位
    {
        for (int j = 0;j<len;j++)
        {
            //将数组中的元素逐一放进它第base位所对应的队列中
            push(bucket[(arr[j]/(int)pow((double)radix,i))%radix],arr[j]);
        }
        int k = 0;

        for (int j = 0;j<len;j++)
        {
            while(!is_empty(bucket[j]))//当队列不为空时,出队列,并继续放到数组中
            {
                pop(bucket[j],&arr[k]); 
                k++;

            }
        }
    }
    for (int i = 0;i<len;i++)
    {
        destory_queue(bucket[i]);
    }
    free(bucket);
} 
int main()
{
    int arr[] = {278,109,63,930,589,184,505,269,8,83};
    int len = sizeof(arr)/sizeof(arr[0]);
    int base = get_base(arr,len);
    int radix = 10;
    base_sort(arr, len, base,radix);
    for (int i=0;i<len;i++)
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
    return 0;
}
--------------------- 
作者:fighting董 
来源:CSDN 
原文:https://blog.csdn.net/qq_35820702/article/details/52975231 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/qq_22771739/article/details/83625289