使用队列进行基数排序

2024-03-09

我想创建一个基数排序 http://en.wikipedia.org/wiki/Radix_sort使用队列实现。

我无法弄清楚我的代码的哪一部分有问题或者我应该阅读哪些资源。 我的代码可能完全错误,但这是我的实现,没有任何帮助(我还没有参加数据结构和算法课程)。

我创建了一个函数,但它不起作用。在进行研究时,我看到了一些代码示例,但它们对我来说似乎更复杂。

Firstly我想找到所有整数的最低有效数字Then将它们排序到下标匹配的队列元素中,then排序后将所有队列复制到第 11 个队列元素的末尾。 在第 11 个队列元素中再次执行此排序,直到达到最高有效数字。

我可以找到最低有效数字。并按照这个数字排序。但是,我无法分析其他数字。例如; 我可以对 1, 2 , 4, 5, 3 进行排序,但是当需要对 2 个或更多数字进行排序时,它会失败......

我希望我很清楚并简要解释了我的问题。

// My function declaration
// Pre: arrInts holds the linked list of integers which are going to be sort.
// Post: queue will return result and its 11th element should hold sorted integers in
//       that queue
queue_node_t * radixSort(const queue_node_t *arrInts, queue_t *queue[], int size){
    queue_node_t *curNodep = arrInts; // Node to be checked
    int i, curNum = curNodep->element.key;
    if(curNodep == NULL){
        // If there is no other node left then assign them into 11th queue.
        for(i=0;i<=9;i++){
            if(queue[i]->rearp!=NULL){
                if(queue[10]->size == 0){
                    queue[10]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
                    queue[10]->frontp = queue[10]->rearp;
                } else {
                    queue[10]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
                    queue[10]->rearp = queue[10]->rearp->restp;
                }
                queue[10]->rearp = queue[i]->rearp;
                queue[10]->size += queue[i]->size;
            }
        }
        queue[10]->rearp = radixSort(queue[10]->rearp, queue, size);
    } else {
                // I used switch statement to handle least significant digit
        switch(curNum%10){
        case 0:
            if(queue[0]->size == 0){
                queue[0]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
                queue[0]->frontp = queue[0]->rearp;
            } else {
                queue[0]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
                queue[0]->rearp = queue[0]->rearp->restp;
            }
            ++(queue[0]->size);
            queue[0]->rearp->element = curNodep->element;
            queue[0]->rearp->restp = NULL;
            radixSort(curNodep->restp, queue, size);
            break;
        case 1:
            if(queue[1]->size == 0){
                queue[1]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
                queue[1]->frontp = queue[0]->rearp;
            } else {
                queue[1]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
                queue[1]->rearp = queue[1]->rearp->restp;
            }
            ++(queue[1]->size);
            queue[1]->rearp->element = curNodep->element;
            queue[1]->rearp->restp = NULL;
                        // I tried to make recursion but I guess this is one the problems
            radixSort(curNodep->restp, queue, size);
            break;
        case 2:
            if(queue[2]->size == 0){
                queue[2]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
                queue[2]->frontp = queue[2]->rearp;
            } else {
                queue[2]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
                queue[2]->rearp = queue[2]->rearp->restp;
            }
            ++(queue[2]->size);
            queue[2]->rearp->element = curNodep->element;
            queue[2]->rearp->restp = NULL;
            radixSort(curNodep->restp, queue, size);
            break;
        case 3:
            if(queue[3]->size == 0){
                queue[3]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
                queue[3]->frontp = queue[3]->rearp;
            } else {
                queue[3]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
                queue[3]->rearp = queue[3]->rearp->restp;
            }
            ++(queue[3]->size);
            queue[3]->rearp->element = curNodep->element;
            queue[3]->rearp->restp = NULL;

            queue[10]->rearp = radixSort(curNodep->restp, queue, size);
            break;
        case 4:
            if(queue[4]->size == 0){
                queue[4]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
                queue[4]->frontp = queue[4]->rearp;
            } else {
                queue[4]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
                queue[4]->rearp = queue[4]->rearp->restp;
            }
            ++(queue[4]->size);
            queue[4]->rearp->element = curNodep->element;
            queue[4]->rearp->restp = NULL;
            radixSort(curNodep->restp, queue, size);
            break;
        case 5:
            if(queue[5]->size == 0){
                queue[5]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
                queue[5]->frontp = queue[5]->rearp;
            } else {
                queue[5]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
                queue[5]->rearp = queue[5]->rearp->restp;
            }
            ++(queue[5]->size);
            queue[5]->rearp->element = curNodep->element;
            queue[5]->rearp->restp = NULL;

            radixSort(curNodep->restp, queue, size);
            break;
        case 6:
            if(queue[6]->size == 0){
                queue[6]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
                queue[6]->frontp = queue[6]->rearp;
            } else {
                queue[6]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
                queue[6]->rearp = queue[6]->rearp->restp;
            }
            ++(queue[6]->size);
            queue[6]->rearp->element = curNodep->element;
            queue[6]->rearp->restp = NULL;

            radixSort(curNodep->restp, queue, size);
            break;
        case 7:
            if(queue[7]->size == 0){
                queue[7]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
                queue[7]->frontp = queue[7]->rearp;
            } else {
                queue[7]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
                queue[7]->rearp = queue[7]->rearp->restp;
            }
            ++(queue[7]->size);
            queue[7]->rearp->element = curNodep->element;
            queue[7]->rearp->restp = NULL;

            radixSort(curNodep->restp, queue, size);
            break;
        case 8:
            if(queue[8]->size == 0){
                queue[8]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
                queue[8]->frontp = queue[8]->rearp;
            } else {
                queue[8]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
                queue[8]->rearp = queue[8]->rearp->restp;
            }
            ++(queue[8]->size);
            queue[8]->rearp->element = curNodep->element;
            queue[8]->rearp->restp = NULL;

            radixSort(curNodep->restp, queue, size);
            break;
        case 9:
            if(queue[9]->size == 0){
                queue[9]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
                queue[9]->frontp = queue[9]->rearp;
            } else {
                queue[9]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
                queue[9]->rearp = queue[9]->rearp->restp;
            }
            ++(queue[9]->size);
            queue[9]->rearp->element = curNodep->element;
            queue[9]->rearp->restp = NULL;

            radixSort(curNodep->restp, queue, size);
            break;
        }
    }

    return queue[10]->rearp;
}

编辑1(取得了一些进展)

我遵循了威廉·莫里斯的建议。我不得不在 CodeReview 上问同样的问题,他给了我一些指示,让我的代码更清晰。

我将函数划分为多个函数,并且也停止使用递归。

Firstly,我创建了一个 add_to_q 函数,该函数为相关队列添加值,并有助于消除代码重复。顺便说一句,James Khoury 的方法是最简单的方法,但它再次使用递归。

void add_to_q(queue_t *queue_arr[], int value, int pos) {
if(queue_arr[pos]->size == 0){
    queue_arr[pos]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
    queue_arr[pos]->frontp = queue_arr[pos]->rearp;
} else {
    queue_arr[pos]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
    queue_arr[pos]->rearp = queue_arr[pos]->rearp->restp;
}
queue_arr[pos]->rearp->element = value;
queue_arr[pos]->size++;
}

Secondly我创建了其他辅助函数。一个是 add_to_eleventh ,它只是将所有队列元素添加到第十一个队列的后面。在我看来,它正在做问题想要的事情。

queue_t * add_to_eleventh(queue_t *queue[]) {
int i;
for(i=0;i<=9;i++){
    while(queue[i]->frontp != NULL){
        if(queue[10]->size == 0){
            queue[10]->rearp = (queue_node_t *)malloc (sizeof(queue_node_t));
            queue[10]->frontp = queue[10]->rearp;
        } else {
            queue[10]->rearp->restp = (queue_node_t *)malloc(sizeof(queue_node_t));
            queue[10]->rearp = queue[10]->rearp->restp;
        }
        if ( queue[i]->size != 0 ){
            queue[10]->rearp->element = queue[i]->frontp->element;
            printf("---%d***",queue[i]->frontp->element);
        }
        queue[10]->size+=1;
        queue[i]->frontp = queue[i]->frontp->restp;
        queue[10]->rearp->restp = NULL;
    }
}
return queue[10];
}

Thirdly,我的最后一个辅助函数是 back_to_ints。其目的是获取第 11 个队列中的元素并将它们除以 10 并以整数数组形式返回它们。

void back_to_ints(queue_t *arr[], int *new_arr) {
queue_node_t *cur_nodep;
cur_nodep = arr[10]->frontp;
int i = 0, digit;
while(cur_nodep != NULL){
    cur_nodep->element/=10;
    digit = cur_nodep->element / 10;
    new_arr[i++] = digit;
    cur_nodep = cur_nodep->restp;
}
}

Finally我的新排序函数现在以相同的数字对整数进行排序。这样,numbers[7] = {112,133,122,334,345,447,346};

queue_t * radix_sort(int *arr, const int size,queue_t *sorted_arr[]) {
int i, digit[size], initials[size],j;
for(i=0;i<size;i++)
    initials[i] = arr[i];
i = 0;
while(initials[i] != 0){
    j = i;
    printf("initialssss%d", initials[--j]);
    back_to_ints(sorted_arr, initials);

    for(i=0;i<size;i++){
    digit[i] = initials[i] % 10;

    switch (digit[i]) {
    case 0:
        add_to_q(sorted_arr, arr[i], 0);
        break;
    case 1:
        add_to_q(sorted_arr, arr[i], 1);
        break;
    case 2:
        add_to_q(sorted_arr, arr[i], 2);
        break;
    case 3:
        add_to_q(sorted_arr, arr[i], 3);
        break;
    case 4:
        add_to_q(sorted_arr, arr[i], 4);
        break;
    case 5:
        add_to_q(sorted_arr, arr[i], 5);
        break;
    case 6:
        add_to_q(sorted_arr, arr[i], 6);
        break;
    case 7:
        add_to_q(sorted_arr, arr[i], 7);
        break;
    case 8:
        add_to_q(sorted_arr, arr[i], 8);
        break;
    case 9:
        add_to_q(sorted_arr, arr[i], 9);
        break;
        }
    }
    sorted_arr[10] = add_to_eleventh(sorted_arr);
    i++;
}
return sorted_arr[10];
}

我部分解决了这个问题。如果你想以相同的数字对数字进行排序,这是可行的。否则,就会失败。例如,您的输入是 112,133,122,334,345,447,346 那么结果将是112 122 133 334 345 346 447。但是,如果用户想要对类似的东西进行排序(111,13,12,334,345,447,1),它会给出111 1 12 13 334 345 447。那么,我该如何克服这个问题呢?

另外,我对头文件做了一些更改。

#ifndef RADIX_H_
#define RADIX_H_

typedef struct queue_node_s {
    int element;
    struct queue_node_s *restp;
}queue_node_t;

typedef struct {
    queue_node_t *frontp,
             *rearp;
    int size;
}queue_t;

queue_t * radix_sort(int *arr,const int size, queue_t *sorted_arr[]);
void add_to_q(queue_t *queue_arr[], int value, int pos);
queue_t * add_to_eleventh(queue_t *queue[]);
void back_to_ints(queue_t *arr[], int *new_arr);
void displayRadixed(queue_t *sorted[]);
#endif /* RADIX_H_ */

谢谢你重新打开我的帖子...


我对你的队列做了一些修改。为了更好地理解代码,我使用 front 和 after 作为全局变量。

typedef struct queue *queue_ptr;
        struct queue {
               int data;
               queue_ptr next;
        };
queue_ptr front[10], rear[10];  /* For base 10, The 11th queue is not needed */

所以添加到队列的操作就变成了

void add_queue(int i, int data) {
        queue_ptr tmp;

        tmp = (queue_ptr) malloc(sizeof(*tmp));
        tmp->next = NULL;
        tmp->data = data;
        if (front[i]) {
                rear[i]->next = tmp;
        } else {
                front[i] = tmp;
        }   
        rear[i] = tmp;
}

并添加删除队列的操作(同时返回数据)

int delete_queue(int i) {
        int data;
        queue_ptr tmp;

        tmp = front[i];
        if (!tmp) {
                return -1;  /* So that we can check if queue is empty */
        }   
        data = tmp->data;
        front[i] = tmp->next;
        free(tmp);
        return data;
}

现在我们可以实现基数排序了。使用实际数字而不是单个数字将数据移入队列可能更容易。请注意,如果您可以修改测试数组 *arr,则不需要第 11 个队列,并且您的 radix_sort 函数可能如下所示:

void radix_sort(int *arr, const int size) {
        int i, j, k, radix, digits, tmp;

        if (size < 1) {
                return;  /* don't do anything if invalid size */
        }

        /* get the number of digits */
        for (digits = 0, radix = 1; arr[0] >= radix; digits++, radix *= 10);

        /* perform sort (digits) times from LSB to MSB */
        for (i = 0, radix = 1; i < digits; i++, radix *= 10) {
                /* distribute into queues */
                for (j = 0; j < size; j++) {
                        add_queue((arr[j] / radix) % 10, arr[j]);
                }
                /* take them out from each queue to the original test array */
                for (j = 0, k = 0; j < 10; j++) {
                        for (tmp = delete_queue(j); tmp != -1;\
                             tmp = delete_queue(j), k++) {
                                arr[k] = tmp;
                        }
                }
        }
}

最后你可以通过调用 radix_sort(your_array, your_array_size) 进行测试,完整代码是

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

typedef struct queue *queue_ptr;
        struct queue {
               int data;
               queue_ptr next;
        };

queue_ptr front[10], rear[10];  /* For base 10, The 11th queue is not needed */

void add_queue(int i, int data) {
        queue_ptr tmp;

        tmp = (queue_ptr) malloc(sizeof(*tmp));
        tmp->next = NULL;
        tmp->data = data;
        if (front[i]) {
                rear[i]->next = tmp;
        } else {
                front[i] = tmp;
        }
        rear[i] = tmp;
}

int delete_queue(int i) {
        int data;
        queue_ptr tmp;

        tmp = front[i];
        if (!tmp) {
                return -1;  /* So that we can check if queue is empty */
        }
        data = tmp->data;
        front[i] = tmp->next;
        free(tmp);
        return data;
}

void radix_sort(int *arr, const int size) {
        int i, j, k, radix, digits, tmp;

        if (size < 1) {
                return;  /* don't do anything if invalid size */
        }

        /* get the number of digits */
        for (digits = 0, radix = 1; arr[0] >= radix; digits++, radix *=10);

        /* perform sort (digits) times from LSB to MSB */
        for (i = 0, radix = 1; i < digits; i++, radix *= 10) {
                /* distribute to queues */
                for (j = 0; j < size; j++) {
                        add_queue((arr[j] / radix) % 10, arr[j]);
                }
                /* take them out from each queue to the original test array */
                for (j = 0, k = 0; j < 10; j++) {
                        for (tmp = delete_queue(j); tmp != -1;\
                             tmp = delete_queue(j), k++) {
                                arr[k] = tmp;
                        }
                }
        }
}

int main(void) {
        int i;
        int a[5] = {133, 34, 555, 111, 12},
            b[12] = {1, 1, 1, 4, 5, 6, 7, 8, 9, 11, 11, 12};

        radix_sort(a, 5);
        radix_sort(b, 5);

        for (i = 0; i < 5; i++) {
                printf("%d ", a[i]);
        }
        printf("\n");

        for (i = 0; i < 12; i++) {
                printf("%d ", b[i]);
        }
        printf("\n");

        return 0;
}

输出是

12 34 111 133 555
1 1 1 4 5 6 7 8 9 11 11 12
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用队列进行基数排序 的相关文章

  • 在 C# 中查找并写入大于 2GB 的文件

    在 C 中 FileStream的方法 Read Write Seek 采用integer在参数中 在一个上一篇文章 https stackoverflow com questions 5654298 filestream read wri
  • 如何在 C# 中将 IEnumerable 转换为 Enum?

    我已将多个字符串解析为枚举标志 但看不到将它们合并为单个枚举位字段的巧妙方法 我使用的方法循环遍历字符串值 然后 将值转换为 Enum 对象 如下所示 Flags public enum MyEnum None 0 First 1 Seco
  • 将阻塞调用包装为异步,以实现更好的线程重用和响应式 UI

    我有一个类负责通过调用遗留类来检索产品可用性 该遗留类本身通过进行 BLOCKING 网络调用在内部收集产品数据 请注意 我无法修改旧版 API 的代码 由于所有产品都是相互独立的 因此我希望并行收集信息 而不会创建任何不必要的线程 也不会
  • 将 Azure Blob 与 Azure 网站连接

    我正在尝试将 Azure 网站连接到 Azure blob 我打算在容器中托管一些文件 然后从我的网站获取它们 我从本教程开始 http azure microsoft com en us documentation articles we
  • (简单)boost thread_group 问题

    我正在尝试编写一个相当简单的线程应用程序 但我对 boost 的线程库很陌生 我正在开发的一个简单的测试程序是 include
  • 对“组件”类型的引用声明它是在“系统”中定义的

    尝试在 UWP 应用程序中获取一些 WMI 对象 在 net 4 6 上运行 VS2015 我收到 ForEach 和方法调用错误 指出 引用类型 组件 声明它是在 系统 中定义的 错误为 CS7069 using System using
  • 哪些 .NET 依赖注入框架值得研究? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 专门化 STL 算法,以便它们在可用时自动调用高效的容器成员函数

    STL 具有全局算法 可以在任意容器上运行 只要它们支持该算法的基本要求 例如 某些算法可能要求容器具有随机访问迭代器 例如向量而不是列表 当容器具有比通用算法更快的执行方式时 它会提供具有相同名称的成员函数来实现相同的目标 就像提供自己的
  • 如何检测并突出显示鼠标悬停时的矩形

    我在 C net 中创建了一个 Windows 应用程序控件 以图形模式显示一些对象 为此 我根据列表中的项目数量创建了一个矩形 并使用 Control OnPaint 事件将其绘制在控件上 现在 如果鼠标悬停在该矩形上 我想突出显示该矩形
  • 如何强制操作系统收回内存? (C++)

    在我的 C 代码中 我分配了大量内存来创建树 然后在每个节点中使用 删除 来释放内存 删除所有内容后 我检查操作系统使用的内存量 发现内存未释放 这是预期的 因为该进程不会立即将内存返回给操作系统 因为它仍然可能会再次使用它 问题是 我在删
  • MaxLength 数据注释是否可以与 List 一起使用?

    一个可以用 MaxLength 具有字符串和简单数组的属性 i e MaxLength 500 public string ProductName get set Or MaxLength 50 public string Products
  • VS Code 不会构建具有多个 .cpp 源文件的 C++ 程序

    请注意 我在 Ubuntu 17 10 上使用 VS Code 并使用 GCC 编译器 我在构建一个使用附加 cpp 文件的简单程序时遇到问题 我可能在这里遗漏了一些明显的东西 因为我对编程相当陌生 但我会解释到目前为止我所做的事情 这阻止
  • 机器人可以从用户处接收图像作为消息或附件吗

    我希望用户能够将图像作为消息发送给机器人 这可能吗 我在网上搜索了解决方案 但我很累 请有人至少可以分享给我一个链接吗 Yes 来自nodejs文档here https learn microsoft com en us azure bot
  • C#等待串口数据

    我试图通过 C 应用程序从指纹扫描仪获取数据 但在指纹发送之前 我的整个代码都会执行 我尝试使用延迟功能System Threading Thread Sleep 1000 因此它可以在下一步执行之前获取数据 但这一切似乎都是徒劳的 任何人
  • L"" 和 u8"" 之间的区别

    以下有什么区别吗 auto s1 L 你好 auto s2 u8 你好 Are s1 and s2指的是同一类型 如果不是 有什么区别以及首选哪一个 它们不是同一类型 s2是 UTF 8 或窄字符串文字 这C 11标准草案 http www
  • 如何分配二维数组? [复制]

    这个问题在这里已经有答案了 我需要创建一个二维数组 目前我将其创建为int a 100 100 但我需要使用动态分配内存malloc在C语言中 我用了代码 include
  • 如何将格式化的电子邮件地址解析为显示名称和电子邮件地址?

    给定电子邮件地址 Jim 电子邮件受保护 gt 如果我尝试将其传递给 MailAddress 我会得到异常 指定的字符串不符合电子邮件地址所需的格式 如何将此地址解析为显示名称 Jim 和电子邮件地址 电子邮件受保护 cdn cgi l e
  • 如何编辑 .csproj 文件

    当我使用 NET Framework 4 0 MSBUILD EXE 文件编译 csproj 文件时 出现错误 在 website01 csproj 的当前上下文中找不到 lable01 实际上 我需要添加每个 ASP NET 页面及其代码
  • 是否可以在 Visual Studio 2010 项目中使用多个“字符集”?

    如您所知 在 Visual Studio 2010 c 中 我们有 noset unicode 和 MBCS 字符集 我们可以通过菜单或预处理器指令 如 define UNICODE 来设置它 我正在开发一个项目 它有一个使用 MBCS 字
  • 人们应该选择 ImmutableDictionary 还是 ImmutableSortedDictionary?

    我听说 NETSystem Collections Immutable集合被实现为平衡二叉树 以满足其不变性约束 甚至是传统上对哈希表进行建模的集合 例如Dictionary 通过使用积分值GetHashCode作为排序键 如果我有一种类型

随机推荐