[英]Radix sort a linked list - linking the buckets
I'm trying to implement radix sort on a linked list based on an integer with the code below.我正在尝试使用下面的代码在基于整数的链表上实现基数排序。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_DIGITS 10 // maximum number of digits in a key
// Structure for a node in the linked list
typedef struct node
{
int key; // the key to be sorted
char value[20]; // the value associated with the key
struct node *next; // pointer to the next node in the list
} Node;
// Function prototypes
void radixSort(Node **head);
Node *createNode(int key, const char *value);
Node *append(Node *head, int key, const char *value);
void printList(Node *head);
int main(void)
{
Node *head = NULL; // head of the linked list
// Create a linked list with some random keys and values
head = append(head, 456, "apple");
head = append(head, 345, "banana");
head = append(head, 123, "cherry");
head = append(head, 789, "date");
head = append(head, 231, "elderberry");
head = append(head, 567, "fig");
head = append(head, 876, "grape");
// Print the original list
printf("Original list:\n");
printList(head);
// Sort the list using radix sort
radixSort(&head);
// Print the sorted list
printf("Sorted list:\n");
printList(head);
return 0;
}
// Function to sort the linked list using radix sort
void radixSort(Node **head)
{
Node *bucket[10]; // array of buckets
Node *curr; // pointer to the current node
Node *tail[10]; // array of tails for each bucket
int i, j, k;
int factor; // factor to sort on
int digits[MAX_DIGITS]; // array to store the digits of the keys
// Initialize the buckets and tails
for (i = 0; i < 10; i++)
{
bucket[i] = NULL;
tail[i] = NULL;
}
// Find the maximum number of digits in the keys
int maxDigits = 0;
curr = *head;
while (curr != NULL)
{
int key = curr->key;
int numDigits = 0;
while (key > 0)
{
numDigits++;
key /= 10;
}
if (numDigits > maxDigits)
{
maxDigits = numDigits;
}
curr = curr->next;
}
// Loop through each digit, starting with the least significant digit
for (factor = 1; maxDigits > 0; factor *= 10, maxDigits--)
{
// Extract the digits of the keys
curr = *head;
while (curr != NULL)
{
digits[curr->key / factor % 10]++;
curr = curr->next;
}
// Cumulative sum of the digits
for (i = 1; i < 10; i++)
{
digits[i] += digits[i - 1];
}
// Sort the nodes into the appropriate buckets
curr = *head;
while (curr != NULL)
{
int digit = curr->key / factor % 10;
if (bucket[digit] == NULL)
{
bucket[digit] = curr;
tail[digit] = curr;
}
else
{
tail[digit]->next = curr;
tail[digit] = curr;
}
curr = curr->next;
}
// Rebuild the list in sorted order
*head = NULL;
for (i = 9; i >= 0; i--)
{
//printf("%dA\n",i);
if (bucket[i] != NULL)
{
//printf("%dB\n",i);
if (*head == NULL)
{
*head = bucket[i];
// printf("%dC\n",i);
}
else
{
//printf("%dD\n",i);
tail[9 - i]->next = bucket[i];
//printf("%dF\n",i);
}
// tail[9 - i] = tail[i];
}
else{
// printf("%dE\n",i);
}
//printf("here\n");
}
}
}
// Function to create a new node with the given key and value
Node *createNode(int key, const char *value)
{
Node *node = (Node*) malloc(sizeof(Node));
node->key = key;
strcpy(node->value, value);
node->next = NULL;
return node;
}
// Function to append a new node with the given key and value to the end of the list
Node *append(Node *head, int key, const char *value)
{
Node *newNode = createNode(key, value);
Node *curr = head;
if (head == NULL)
{
return newNode;
}
while (curr->next != NULL)
{
curr = curr->next;
}
curr->next = newNode;
return head;
}
// Function to print the linked list
void printList(Node *head)
{
Node *curr = head;
while (curr != NULL)
{
printf("(%d, %s) ", curr->key, curr->value);
curr = curr->next;
}
printf("\n");
}
The segmentation fault occurs when tail[9 - i]->next = bucket[i];
当
tail[9 - i]->next = bucket[i];
时发生段错误is executed.被执行。
I added printf
statements (turned them into comment blocks) to trace where the error is.我添加了
printf
语句(将它们变成注释块)来跟踪错误所在。 Can someone please help me figure out a way to get this to work?有人可以帮我想办法让它工作吗?
There are a few issues:有几个问题:
tail[9 - i]->next = bucket[i];
sets the wrong pointer.设置错误的指针。 There is no reason why it should be
9 - i
.没有理由应该是
9 - i
。 It could even be that tail[9 - i]
is NULL. tail[9 - i]
甚至可能是 NULL。 So this leads to indefined behaviour.所以这会导致不确定的行为。 Instead you should keep track of what the current tail node is in the list that is being built.
相反,您应该跟踪正在构建的列表中的当前尾节点。 You could use
curr
for that purpose.您可以为此目的使用
curr
。 Let it start (before the loop) with curr = NULL
and then when you find a non-null bucket, end that process by setting curr = tail[i]
.让它从
curr = NULL
开始(在循环之前),然后当您找到一个非空桶时,通过设置curr = tail[i]
结束该过程。 When a bucket is found when the *head
is no longer NULL
, make the link with curr->next = bucket[i]
.当
*head
不再为NULL
时找到桶时,使用curr->next = bucket[i]
建立链接。
The new list is not terminated with a NULL
pointer.新列表未以
NULL
指针终止。 When the above point is implemented, continue after the loop with curr->next = NULL
.实现上述点后,在
curr->next = NULL
循环后继续。
In the next iteration of the factor
loop, both digits
and buckets
need to be reset.在
factor
循环的下一次迭代中, digits
和buckets
都需要重置。 You could do this with a loop or with memset
.您可以使用循环或使用
memset
来执行此操作。
Here is the corrected factor
loop code -- comments indicate where corrections were made:这是更正后的
factor
循环代码——注释指出了更正的地方:
for (factor = 1; maxDigits > 0; factor *= 10, maxDigits--)
{
memset(digits, 0, sizeof(digits)); // reset!
memset(bucket, 0, sizeof(bucket)); // reset!
curr = *head;
while (curr != NULL)
{
digits[curr->key / factor % 10]++;
curr = curr->next;
}
for (i = 1; i < 10; i++)
{
digits[i] += digits[i - 1];
}
curr = *head;
while (curr != NULL)
{
int digit = curr->key / factor % 10;
if (bucket[digit] == NULL)
{
bucket[digit] = curr;
tail[digit] = curr;
}
else
{
tail[digit]->next = curr;
tail[digit] = curr;
}
curr = curr->next;
}
*head = NULL;
curr = NULL; // <-- track the current tail of the newly built list
for (i = 9; i >= 0; i--)
{
if (bucket[i] != NULL)
{
if (*head == NULL)
{
*head = bucket[i];
}
else
{
curr->next = bucket[i]; // Append bucket after the current tail
}
curr = tail[i]; // The tail is now at the end of this bucket
}
}
curr->next = NULL; // Terminate the list properly
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.