C语言实现基数排序——基于链队列实现

C语言实现基数排序

基数排序算法

1.定义链结构

//定义链结构
typedef struct LinkNode {
    int data;
    struct LinkNode *next;
} LinkNode;

2.定义链队列结构

//定义链队列
typedef struct {
    LinkNode *front, *rear;
} LinkQueue;

3.初始化带头结点的链队列

//初始化带头结点的链式队列
void InitQueue(LinkQueue &Q) {
    //初始时 front和rear都指向头结点
    Q.front = Q.rear = (LinkNode *) malloc(sizeof(LinkNode));
    Q.front->next = NULL;
}

4.判断带头结点的链队列是否为空

//初始化带头结点的链式队列
void InitQueue(LinkQueue &Q) {
    //初始时 front和rear都指向头结点
    Q.front = Q.rear = (LinkNode *) malloc(sizeof(LinkNode));
    Q.front->next = NULL;
}
}

5.带头结点的链队列入队操作

//带头结点的链式队列入队操作
void EnQueue(LinkQueue &Q, int x) {
    LinkNode *p = (LinkNode *) malloc(sizeof(LinkNode));
    p->data = x;
    p->next = NULL;
    Q.rear->next = p;
    Q.rear = p;
}

6.带头结点的链队列出队操作

//带头结点的链式队列出队操作
bool DeQueue(LinkQueue &Q, int &x) {
    if (Q.front == Q.rear)          //判断是否为空队
        return false;
    LinkNode *p = Q.front->next;    //将要出队的结点命名为p
    x = p->data;                    //用变量x返回队头元素
    Q.front->next = p->next;        //修改头结点的next指针
    if (Q.rear == p)                //判断要出队的是否为最后一个结点
        Q.rear = Q.front;           //如果是最后一个,就将队尾指针rear指向队头front
    free(p);                        //释放要删除结点的空间
    return true;
}

7.取a的个位、十位、百位…的值

//取各个位的值
int GetNum(int a, int i) {
    int n;
    if (i == 1)
        n = a / 1 % 10;
    else {
        int k = (int) pow(10, i - 1);
        n = a / k % 10;
    }
    return n;
}

8.检索表中最大的值是几位数

//检索表中最大值的位数
int HowMany(int A[], int len) {
    if (len == 0)
        return -1;
    int index = 1;
    for (int i = 0; i < len; ++i) {
        int temp = 1;
        int a = 10;
        while (A[i] / a > 0) {
            temp++;
            a *= 10;
        }
        if (index < temp)
            index = temp;
    }
    return index;
}

9.基数排序算法的实现

//基数排序
void BaseSort(int A[], LinkQueue Q[], int index, int len) {
    for (int i = 1; i <= index; ++i) {      //表中最大值是几位数就需要循环几趟
        for (int j = 0; j < len; ++j) {
            int k = GetNum(A[j], i);        //获取A表中各个值在第i位上的值
            EnQueue(Q[k], A[j]);         //将A表中各个值按照第i位的值插入对应队列
        }
        for (int j = 9, p = 0; j >= 0 && p < len; --j) {    //循环所有的链队列
            while (!IsEmpty(Q[j])) {        //若队列非空,循环出队并将出队的元素依次插入A表中
                int x;
                DeQueue(Q[j], x);
                A[p] = x;
                p++;
            }
        }
    }
}

项目完整代码

//基数排序(稳定的)
#include <stdio.h>
#include <stdlib.h>
#include <cmath>

//定义链结构
typedef struct LinkNode {
    int data;
    struct LinkNode *next;
} LinkNode;

//定义链队列
typedef struct {
    LinkNode *front, *rear;
} LinkQueue;

//初始化带头结点的链式队列
void InitQueue(LinkQueue &Q) {
    //初始时 front和rear都指向头结点
    Q.front = Q.rear = (LinkNode *) malloc(sizeof(LinkNode));
    Q.front->next = NULL;
}

//判断带头结点的链式队列是否为空
bool IsEmpty(LinkQueue Q) {
    if (Q.front == Q.rear || Q.front->next == NULL)
        return true;
    else
        return false;
}

//带头结点的链式队列入队操作
void EnQueue(LinkQueue &Q, int x) {
    LinkNode *p = (LinkNode *) malloc(sizeof(LinkNode));
    p->data = x;
    p->next = NULL;
    Q.rear->next = p;
    Q.rear = p;
}

//带头结点的链式队列出队操作
bool DeQueue(LinkQueue &Q, int &x) {
    if (Q.front == Q.rear)          //判断是否为空队
        return false;
    LinkNode *p = Q.front->next;    //将要出队的结点命名为p
    x = p->data;                    //用变量x返回队头元素
    Q.front->next = p->next;        //修改头结点的next指针
    if (Q.rear == p)                //判断要出队的是否为最后一个结点
        Q.rear = Q.front;           //如果是最后一个,就将队尾指针rear指向队头front
    free(p);                        //释放要删除结点的空间
    return true;
}

//取各个位的值
int GetNum(int a, int i) {
    int n;
    if (i == 1)
        n = a / 1 % 10;
    else {
        int k = (int) pow(10, i - 1);
        n = a / k % 10;
    }
    return n;
}

//检索表中最大值的位数
int HowMany(int A[], int len) {
    if (len == 0)
        return -1;
    int index = 1;
    for (int i = 0; i < len; ++i) {
        int temp = 1;
        int a = 10;
        while (A[i] / a > 0) {
            temp++;
            a *= 10;
        }
        if (index < temp)
            index = temp;
    }
    return index;
}

//基数排序
void BaseSort(int A[], LinkQueue Q[], int index, int len) {
    for (int i = 1; i <= index; ++i) {      //表中最大值是几位数就需要循环几趟
        for (int j = 0; j < len; ++j) {
            int k = GetNum(A[j], i);        //获取A表中各个值在第i位上的值
            EnQueue(Q[k], A[j]);         //将A表中各个值按照第i位的值插入对应队列
        }
        for (int j = 9, p = 0; j >= 0 && p < len; --j) {    //循环所有的链队列
            while (!IsEmpty(Q[j])) {        //若队列非空,循环出队并将出队的元素依次插入A表中
                int x;
                DeQueue(Q[j], x);
                A[p] = x;
                p++;
            }
        }
    }
}

int main() {
    //声明链队列
    LinkQueue Q[10];
    //初始化链队列
    for (int i = 0; i < 10; ++i) {
        InitQueue(Q[i]);
    }

    int A[] = {520, 211, 456, 888, 8, 111, 985, 666, 996, 233, 168, 66, 9999};
    int len = sizeof(A) / sizeof(int);

    //检索表中最大值的位数
    int index = HowMany(A, len);

    //基数排序
    BaseSort(A, Q, index, len);
    //将排序后的结果输出
    printf("基数排序的结果为:");
    for (int i = 0; i < len; ++i) {
        printf("%d ", A[i]);
    }
    return 0;
}

运行效果图

    int A[] = {520, 211, 456, 888, 8, 111, 985, 666, 996, 233, 168, 66, 9999};

在这里插入图片描述

链式基数排序是一种基于链表的排序算法,用于对数据进行多关键字排序。它的基本思想是将单个关键字拆分成若干项,并将每一项作为一个新的关键字进行排序。对于整数或字符串类型的关键字,可以将其拆分为单个数字或单个字母。 链式基数排序的具体步骤如下: 1. 定义链结构和链队列结构。 2. 初始化带头结点的链队列。 3. 判断带头结点的链队列是否为空,如果为空则说明排序完成。 4. 从最低位的关键字开始,将序列中的数据根据关键字的不同值分配到不同的队列中。 5. 按关键字从小到大(升序)收集起来。 6. 重复上述步骤,直到最高位分配—收集完成,此时序列有序。 下面是一个示例代码的实现: ```c #include <stdio.h> #include <stdlib.h> #define MAX_DIGIT 10 // 假设关键字的最大位数为10 // 定义链结构 typedef struct node { int data; struct node* next; } Node; // 定义链队列结构 typedef struct queue { Node* front; // 队头指针 Node* rear; // 队尾指针 } Queue; // 初始化带头结点的链队列 void initQueue(Queue* q) { q->front = q->rear = (Node*)malloc(sizeof(Node)); q->front->next = NULL; } // 判断带头结点的链队列是否为空 int isQueueEmpty(Queue* q) { return (q->front == q->rear); } // 带头结点的链队列入队操作 void enqueue(Queue* q, int data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; q->rear->next = newNode; q->rear = newNode; } // 带头结点的链队列出队操作 int dequeue(Queue* q) { if (isQueueEmpty(q)) { printf("Error: Queue is empty\n"); exit(EXIT_FAILURE); } Node* temp = q->front->next; int data = temp->data; q->front->next = temp->next; if (q->rear == temp) { // 若删除的是最后一个结点,则修改队尾指针 q->rear = q->front; } free(temp); return data; } // 取关键字的某一位的值 int getDigit(int num, int digit) { int i; for (i = 0; i < digit; i++) { num /= 10; } return num % 10; } // 检索表中最大的值是几位数 int getMaxDigit(int* arr, int length) { int maxDigit = 1; int i; for (i = 1; i < length; i++) { if (arr[i > arr[i - 1]) { maxDigit = arr[i]; } } int digit = 0; while (maxDigit) { maxDigit /= 10; digit++; } return digit; } // 基数排序算法的实现 void radixSort(int* arr, int length) { int maxDigit = getMaxDigit(arr, length); int i, j, k; Queue queues
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值