实现基数排序算法

基数排序介绍

基数排序是桶排序的扩展,它的基本思想是:将整数按位数切割成不同的数字,然后按每个位数分别比较。

具体做法是:

将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

基数排序图文说明

通过基数排序对数组{53, 542, 3, 63, 14, 214, 154, 748, 616},它的示意图如下:

在上图中,首先将所有待比较数值统一为统一位数长度,接着从最低位开始,依次进行排序。
1. 按照个位数进行排序。
2. 按照十位数进行排序。
3. 按照百位数进行排序。
排序后,数列就变成了一个有序序列。

/**
*    实验题目:
*        实现基数排序算法
*    实验目的:
*        领会基数排序的过程和算法设计
*    实验内容:
*        设计程序,实现基数排序算法。用相关数据进行测试,并
*    输出各趟的排序结果。
*    基数排序基本思想:
*        将整数按位数切割成不同的数字,然后按每个位数分别比较。
*    基数排序具体做法:
*        将所有待比较数值统一为同样的数位长度,数位较短的数前面
*    补零。然后,从最低位开始,依次进行一次排序。这样从最低位排
*    序一直到最高位排序完成以后, 数列就变成一个有序序列。
*    备注:
*        这里基数排序的关键字为整数,采用从低位到高位即最低位优先
*    的排序方式。排序数据采用不带头结点的单链表存放。
*/

#include <stdio.h>
#include <malloc.h>

#define MAXE    (20)                                    //  线性表中最多元素个数
#define MAXR    (10)                                    //  基数的最大取值

typedef struct node
{
    int key;                                            //  记录的关键字
    struct node *next;
}node_type;                                             //  单链表的结点类型

/*-----------采用尾插法由a[0..n-1]创建首结点指针为p的单链表-------------*/
static void create_link(node_type *&p, int a[], int n)          //  指针的引用
{
    node_type *s, *t;

    for(int i = 0; i < n; i++)
    {
        s = (node_type *)malloc(sizeof(node_type));
        s->key = a[i];
        if(i == 0)
        {
            p = s;
            t = s;
        }
        else
        {
            t->next = s;
            t = s;
        }
    }
    t->next = NULL;                                             //  尾结点的next域置NULL
}

/*-----------输出单链表-------------*/
static void disp_link(node_type *p)
{
    while(p != NULL)
    {
        printf("%4d", p->key);
        p = p->next;
    }
    printf("\n");
}

/*-----------销毁单链表-------------*/
static void destroy_link(node_type *p)
{
    node_type *pre = p;
    node_type *q = pre->next;

    while(q != NULL)
    {
        free(pre);
        pre = q;
        q = q->next;
    }
    free(pre);
}

/*-----------对于数值num,从低位到高位,取第i位的数字-------------*/
static int keyi(int num, int i)
{
    int j;

    for(j = 0; j < i; j++)
        num = num / 10;

    return num % 10;
}

/**
*   功能:
*       实现最低位优先的基数排序
*   参数:
*       p指向单链表的首结点
*       r为基数
*       d为关键字位数
*/
static void radix_sort(node_type *&p, int r, int d)     //  指针的引用
{
    node_type *head[MAXR], *tail[MAXR], *t;             //  定义各链队的首尾指针
    int i, j, k;

    for(i = 0; i < d; i++)                              //  从低位到高位循环
    {
        for(j = 0; j < r; j++)                          //  初始化各链队首、尾指针
            head[j] = tail[j] = NULL;

        while(p != NULL)                                //  对于原链表中每个结点循环
        {
            k = keyi(p->key, i);                        //  找p结点关键字的第i位k
            printf("第%d位为%d\n", i + 1, k);
            if(head[k] == NULL)                         //  将p结点分配到第k个链队
            {
                head[k] = p;
                tail[k] = p;
            }
            else
            {
                tail[k]->next = p;
                tail[k] = p;
            }
            p = p->next;                                //  继续扫描下一个结点
        }
        p = NULL;
        for(j = 0; j < r; j++)                          //  对于每一个链队循环
        {
            if(head[j] != NULL)                         //  进行收集
            {
                if(p == NULL)
                {
                    p = head[j];
                    t = tail[j];
                }
                else
                {
                    t->next = head[j];
                    t = tail[j];
                }
            }
        }
        t->next = NULL;
        printf("按%d位排序:", i + 1);
        disp_link(p);
    }
}

int main(int argc, char *argv[])
{
    int n = 10;
    node_type *p;
    int a[] = {75, 223, 98, 44, 157, 2, 29, 164, 38, 82};

    create_link(p, a, n);
    printf("   排序前:");
    disp_link(p);
    radix_sort(p, 10, 3);
    printf("   排序后:");
    disp_link(p);
    destroy_link(p);

    return 0;
}

测试结果:

排序前:  75 223  98  44 157   2  29 164  38  82
第1位为5
第1位为3
第1位为8
第1位为4
第1位为7
第1位为2
第1位为9
第1位为4
第1位为8
第1位为2
按1位排序:   2  82 223  44 164  75 157  98  38  29
第2位为0
第2位为8
第2位为2
第2位为4
第2位为6
第2位为7
第2位为5
第2位为9
第2位为3
第2位为2
按2位排序:   2 223  29  38  44 157 164  75  82  98
第3位为0
第3位为2
第3位为0
第3位为0
第3位为0
第3位为1
第3位为1
第3位为0
第3位为0
第3位为0
按3位排序:   2  29  38  44  75  82  98 157 164 223
   排序后:   2  29  38  44  75  82  98 157 164 223

猜你喜欢

转载自blog.csdn.net/xiezhi123456/article/details/87364289