实现英文单词按词典序排列的基数排序算法

/**
*    实验题目:
*        实现英文单词按词典序排列的基数排序算法
*    实验目的:
*        掌握基数排序算法及其应用
*    实验内容:
*        编写程序,采用基数排序方法将一组英文单词按词典序排列。假设
*    单词均由小写字母或空格构成,最长的单词有MAX_LEN个字母,用相关
*    数据进行测试,并输出各趟的排序结果。
*/

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

#define MAX_LEN 9                               //  单词的最大长度
#define RADIX 27                                //  基数rd为27,分别对应' ','a',...,'z'

typedef char String[MAX_LEN + 1];               //  定义String为字符数组类型
typedef struct node
{
    String word;
    struct node *next;
}link_node;                                     //  单链表结点类型

/*------------------输出单词------------------------*/
static void disp_word(String R[], int n)
{
    int i;

    printf("  ");
    for(i = 0; i < n; i++)
    {
        printf("[%s] ", R[i]);
    }
    printf("\n");
}

/*------------------对单词进行预处理,用空格填充尾部至MAX_LEN长------------------------*/
static void pre_process(String R[], int n)
{
    int i, j;

    for(i = 0; i < n; i++)
    {
        if(strlen(R[i]) < MAX_LEN)
        {
            for(j = strlen(R[i]); j < MAX_LEN; j++)
            {
                R[i][j] = ' ';
            }
            R[i][j] = '\0';
        }
    }
}

/*---------------恢复处理,删除预处理时填充的尾部空格--------------------*/
static void end_process(String R[], int n)
{
    int i, j;

    for(i = 0; i < n; i++)
    {
        for(j = MAX_LEN - 1; R[i][j] == ' '; j--)
            R[i][j + 1] = '\0';
    }
}

/*--------------按关键字的第j个分量进行分配,进入此过程时各队列一定为空--------------*/
static void distribute(String R[], link_node *head[], link_node *tail[], int j, int n)
{
    int i;                                          //  循环变量
    int k;                                          //  队列编号
    link_node *p;

    for(i = 0; i < n; i++)                          //  依次扫描R[i],将其入队
    {
        if(R[i][j] == ' ')                          //  空格时放入0号队列中,'a'放入1号队列中,......
            k = 0;
        else
            k = R[i][j] - 'a' + 1;
        p = (link_node *)malloc(sizeof(link_node)); //  创建新结点
        strcpy(p->word, R[i]);
        p->next = NULL;
        if(head[k] == NULL)
        {
            head[k] = p;
            tail[k] = p;
        }
        else
        {
            tail[k]->next = p;
            tail[k] = p;
        }
    }
}

/*--------------依次将各非空队列中的结点收集起来,并释放各非空队列中的所有结点--------------*/
static void collect(String R[], link_node *head[])
{
    int i;
    int k = 0;
    link_node *pre, *p;

    for(i = 0; i < RADIX; i++)
    {
        if(head[i] != NULL)
        {
            pre = head[i];
            p = pre->next;
            while(p != NULL)
            {
                strcpy(R[k++], pre->word);
                free(pre);
                pre = p;
                p = p->next;
            }
            strcpy(R[k++], pre->word);
            free(pre);
        }
    }
}

/*------------------对R[0...n-1]进行基数排序----------------*/
static void radix_sort(String R[], int n)
{
    int i, j;
    link_node *head[RADIX], *tail[RADIX];

    for(i = MAX_LEN - 1; i >= 0; i--)                       //  从低位到高位做MAX_LEN趟基数排序
    {
        for(j = 0; j < RADIX; j++)
            head[j] = tail[j] = NULL;
        distribute(R, head, tail, i, n);                    //  第i趟分配
        collect(R, head);                                   //  第i趟收集
    }
}

int main(void)
{
    int n = 6;
    String R[] = {"while", "if", "if else", "do while", "for", "case"};

    printf("排序前:\n");
    disp_word(R, n);
    pre_process(R, n);
    printf("预处理后:\n");
    disp_word(R, n);
    radix_sort(R, n);
    printf("排序结果:\n");
    disp_word(R, n);
    end_process(R, n);
    printf("最终结果:\n");
    disp_word(R, n);

    return 0;
}
测试结果:

排序前:
  [while] [if] [if else] [do while] [for] [case]
预处理后:
  [while    ] [if       ] [if else  ] [do while ] [for      ] [case     ]
排序结果:
  [case     ] [do while ] [for      ] [if       ] [if else  ] [while    ]
最终结果:
  [case ] [do while ] [for ] [if ] [if else ] [while ]

猜你喜欢

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