c语言中如何用链表进行排序

c语言中如何用链表进行排序

C语言中如何用链表进行排序

在C语言中使用链表进行排序时,我们可以选择多种不同的排序算法来实现,比如插入排序、快速排序、归并排序等。归并排序在链表上的表现尤为出色,因为它不需要随机访问元素,只需进行顺序访问。下面我们详细讨论使用归并排序来对链表进行排序的过程。

一、链表的基本操作

在进行排序之前,我们需要了解链表的一些基本操作,包括创建链表、插入节点、删除节点以及遍历链表。

1. 创建链表

在C语言中,链表通常由一个结构体表示,每个结构体包含数据域和指向下一个节点的指针。

struct Node {

int data;

struct Node* next;

};

2. 插入节点

插入节点是链表操作的基础,可以在链表的头部、尾部或中间插入节点。

void insertAtHead(struct Node head, int data) {

struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));

newNode->data = data;

newNode->next = *head;

*head = newNode;

}

3. 删除节点

删除节点时需要找到要删除的节点并调整前一个节点的指针。

void deleteNode(struct Node head, int key) {

struct Node* temp = *head;

struct Node* prev = NULL;

if (temp != NULL && temp->data == key) {

*head = temp->next;

free(temp);

return;

}

while (temp != NULL && temp->data != key) {

prev = temp;

temp = temp->next;

}

if (temp == NULL) return;

prev->next = temp->next;

free(temp);

}

4. 遍历链表

遍历链表可以打印链表中的每个节点的数据。

void printList(struct Node* node) {

while (node != NULL) {

printf("%d -> ", node->data);

node = node->next;

}

printf("NULLn");

}

二、归并排序在链表中的实现

归并排序是一种有效的排序算法,尤其适合链表,因为它不需要随机访问元素。我们将归并排序分为两个部分:拆分链表和合并排序后的链表。

1. 拆分链表

拆分链表的目的是将链表分成两个子链表,直到每个子链表只有一个节点。

struct Node* getMiddle(struct Node* head) {

if (head == NULL) return head;

struct Node* slow = head;

struct Node* fast = head->next;

while (fast != NULL) {

fast = fast->next;

if (fast != NULL) {

slow = slow->next;

fast = fast->next;

}

}

return slow;

}

2. 合并排序后的链表

合并两个排序后的链表是归并排序的核心步骤。

struct Node* sortedMerge(struct Node* a, struct Node* b) {

struct Node* result = NULL;

if (a == NULL) return b;

if (b == NULL) return a;

if (a->data <= b->data) {

result = a;

result->next = sortedMerge(a->next, b);

} else {

result = b;

result->next = sortedMerge(a, b->next);

}

return result;

}

3. 归并排序的主函数

归并排序的主函数将链表拆分并递归地排序和合并。

void mergeSort(struct Node headRef) {

struct Node* head = *headRef;

struct Node* a;

struct Node* b;

if ((head == NULL) || (head->next == NULL)) {

return;

}

struct Node* middle = getMiddle(head);

struct Node* nextOfMiddle = middle->next;

middle->next = NULL;

mergeSort(&head);

mergeSort(&nextOfMiddle);

*headRef = sortedMerge(head, nextOfMiddle);

}

三、应用示例

以下是一个完整的示例,展示如何使用归并排序对链表进行排序。

#include <stdio.h>

#include <stdlib.h>

struct Node {

int data;

struct Node* next;

};

void insertAtHead(struct Node head, int data) {

struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));

newNode->data = data;

newNode->next = *head;

*head = newNode;

}

struct Node* getMiddle(struct Node* head) {

if (head == NULL) return head;

struct Node* slow = head;

struct Node* fast = head->next;

while (fast != NULL) {

fast = fast->next;

if (fast != NULL) {

slow = slow->next;

fast = fast->next;

}

}

return slow;

}

struct Node* sortedMerge(struct Node* a, struct Node* b) {

struct Node* result = NULL;

if (a == NULL) return b;

if (b == NULL) return a;

if (a->data <= b->data) {

result = a;

result->next = sortedMerge(a->next, b);

} else {

result = b;

result->next = sortedMerge(a, b->next);

}

return result;

}

void mergeSort(struct Node headRef) {

struct Node* head = *headRef;

struct Node* a;

struct Node* b;

if ((head == NULL) || (head->next == NULL)) {

return;

}

struct Node* middle = getMiddle(head);

struct Node* nextOfMiddle = middle->next;

middle->next = NULL;

mergeSort(&head);

mergeSort(&nextOfMiddle);

*headRef = sortedMerge(head, nextOfMiddle);

}

void printList(struct Node* node) {

while (node != NULL) {

printf("%d -> ", node->data);

node = node->next;

}

printf("NULLn");

}

int main() {

struct Node* head = NULL;

insertAtHead(&head, 15);

insertAtHead(&head, 10);

insertAtHead(&head, 5);

insertAtHead(&head, 20);

insertAtHead(&head, 3);

insertAtHead(&head, 2);

printf("Unsorted list: n");

printList(head);

mergeSort(&head);

printf("Sorted list: n");

printList(head);

return 0;

}

四、其他排序算法在链表中的实现

除了归并排序,链表还可以使用其他排序算法,比如插入排序和快速排序。

1. 插入排序

插入排序适用于链表,因为它可以在O(1)时间内完成插入操作。

void sortedInsert(struct Node headRef, struct Node* newNode) {

struct Node* current;

if (*headRef == NULL || (*headRef)->data >= newNode->data) {

newNode->next = *headRef;

*headRef = newNode;

} else {

current = *headRef;

while (current->next != NULL && current->next->data < newNode->data) {

current = current->next;

}

newNode->next = current->next;

current->next = newNode;

}

}

void insertionSort(struct Node headRef) {

struct Node* sorted = NULL;

struct Node* current = *headRef;

while (current != NULL) {

struct Node* next = current->next;

sortedInsert(&sorted, current);

current = next;

}

*headRef = sorted;

}

2. 快速排序

快速排序在链表上实现相对复杂,但它的时间复杂度在平均情况下为O(n log n)。

struct Node* partition(struct Node* head, struct Node* end, struct Node newHead, struct Node newEnd) {

struct Node* pivot = end;

struct Node* prev = NULL;

struct Node* cur = head;

struct Node* tail = pivot;

while (cur != pivot) {

if (cur->data < pivot->data) {

if ((*newHead) == NULL) {

(*newHead) = cur;

}

prev = cur;

cur = cur->next;

} else {

if (prev) {

prev->next = cur->next;

}

struct Node* temp = cur->next;

cur->next = NULL;

tail->next = cur;

tail = cur;

cur = temp;

}

}

if ((*newHead) == NULL) {

(*newHead) = pivot;

}

(*newEnd) = tail;

return pivot;

}

struct Node* quickSortRecur(struct Node* head, struct Node* end) {

if (!head || head == end) {

return head;

}

struct Node* newHead = NULL;

struct Node* newEnd = NULL;

struct Node* pivot = partition(head, end, &newHead, &newEnd);

if (newHead != pivot) {

struct Node* temp = newHead;

while (temp->next != pivot) {

temp = temp->next;

}

temp->next = NULL;

newHead = quickSortRecur(newHead, temp);

temp = getTail(newHead);

temp->next = pivot;

}

pivot->next = quickSortRecur(pivot->next, newEnd);

return newHead;

}

void quickSort(struct Node headRef) {

(*headRef) = quickSortRecur(*headRef, getTail(*headRef));

}

五、总结

在C语言中对链表进行排序时,选择合适的排序算法至关重要。归并排序由于其优良的性能和稳定性,通常是链表排序的首选。插入排序适用于小规模数据,而快速排序适用于需要更高效率的情况。无论选择哪种排序算法,都需要根据链表的具体情况进行调整和优化。在实际项目管理中,使用高效的项目管理系统如研发项目管理系统PingCode通用项目管理软件Worktile,可以帮助团队更好地跟踪和管理开发进度,确保项目顺利进行。

相关问答FAQs:

Q: 如何在C语言中使用链表进行排序?
A: 链表排序是一种常见的操作,以下是一种基本的链表排序算法:

  1. 首先,定义一个指向链表头节点的指针,并将其初始化为NULL。
  2. 然后,创建一个新的链表节点,并将其插入到链表中的正确位置。这可以通过遍历链表并比较节点值来实现。
  3. 在比较节点值时,如果要插入的节点值小于当前节点值,则将要插入的节点插入到当前节点之前。
  4. 如果要插入的节点值大于当前节点值,则继续遍历链表直到找到合适的位置。
  5. 重复步骤3和步骤4,直到所有节点都被插入到新链表中。
  6. 最后,将原链表头节点指针指向新链表的头节点。

Q: 如何在C语言中实现链表的升序排序?
A: 以下是一种实现链表升序排序的方法:

  1. 首先,定义一个指向链表头节点的指针,并将其初始化为NULL。
  2. 然后,逐个读取输入的数据,并创建一个新的链表节点。
  3. 在插入新节点时,遍历链表并找到正确的位置。如果要插入的节点值小于当前节点值,则将要插入的节点插入到当前节点之前。如果要插入的节点值大于等于当前节点值,则继续遍历链表直到找到合适的位置。
  4. 重复步骤3,直到所有节点都被插入到链表中。
  5. 最后,将链表头节点指针指向排序后的链表的头节点。

Q: C语言中如何使用链表进行降序排序?
A: 以下是一种实现链表降序排序的方法:

  1. 首先,定义一个指向链表头节点的指针,并将其初始化为NULL。
  2. 然后,逐个读取输入的数据,并创建一个新的链表节点。
  3. 在插入新节点时,遍历链表并找到正确的位置。如果要插入的节点值大于当前节点值,则将要插入的节点插入到当前节点之前。如果要插入的节点值小于等于当前节点值,则继续遍历链表直到找到合适的位置。
  4. 重复步骤3,直到所有节点都被插入到链表中。
  5. 最后,将链表头节点指针指向排序后的链表的头节点。

原创文章,作者:Edit1,如若转载,请注明出处:https://docs.pingcode.com/baike/1041111

(0)
Edit1Edit1
上一篇 2024年8月27日 下午4:42
下一篇 2024年8月27日 下午4:42
免费注册
电话联系

4008001024

微信咨询
微信咨询
返回顶部