c语言链表如何排序

c语言链表如何排序

C语言链表如何排序这一问题的核心观点包括:使用插入排序、使用合并排序、使用快速排序、对链表节点进行交换、递归和迭代方法。在链表中,使用合并排序是一种常见且高效的排序方法,因为它能够有效地处理链表的分割和合并操作。合并排序的时间复杂度为O(n log n),适用于大多数情况下的链表排序。

一、使用插入排序

插入排序是一种简单且直观的排序算法,特别适合于小规模数据的排序。在链表中,插入排序的实现需要遍历链表,并将每个节点插入到已排序部分的正确位置。

插入排序的具体步骤如下:

  1. 初始化已排序链表:从原始链表中取出第一个节点,作为已排序链表的起点。
  2. 遍历剩余节点:逐个遍历原始链表中的节点,并将每个节点插入到已排序链表的正确位置。
  3. 插入节点:通过比较已排序链表中的节点值,找到合适的位置进行插入。

#include <stdio.h>

#include <stdlib.h>

typedef struct Node {

int data;

struct Node* next;

} Node;

void sortedInsert(Node head_ref, Node* new_node) {

Node* current;

if (*head_ref == NULL || (*head_ref)->data >= new_node->data) {

new_node->next = *head_ref;

*head_ref = new_node;

} else {

current = *head_ref;

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

current = current->next;

}

new_node->next = current->next;

current->next = new_node;

}

}

void insertionSort(Node head_ref) {

Node* sorted = NULL;

Node* current = *head_ref;

while (current != NULL) {

Node* next = current->next;

sortedInsert(&sorted, current);

current = next;

}

*head_ref = sorted;

}

// Helper functions to create and print the linked list

void push(Node head_ref, int new_data) {

Node* new_node = (Node*)malloc(sizeof(Node));

new_node->data = new_data;

new_node->next = *head_ref;

*head_ref = new_node;

}

void printList(Node* node) {

while (node != NULL) {

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

node = node->next;

}

}

int main() {

Node* head = NULL;

push(&head, 5);

push(&head, 20);

push(&head, 4);

push(&head, 3);

push(&head, 30);

printf("Linked list before sorting:n");

printList(head);

insertionSort(&head);

printf("nLinked list after sorting:n");

printList(head);

return 0;

}

二、使用合并排序

合并排序是一种分治算法,在链表排序中非常高效,因为它能够很好地处理链表的分割和合并操作。合并排序的时间复杂度为O(n log n),适用于大多数情况下的链表排序。

合并排序的具体步骤如下:

  1. 分割链表:递归地将链表分割成两半,直到每个子链表只包含一个节点。
  2. 合并链表:递归地合并两个已排序的子链表,直到整个链表重新组合成一个已排序的链表。

#include <stdio.h>

#include <stdlib.h>

typedef struct Node {

int data;

struct Node* next;

} Node;

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

Node* result = NULL;

if (a == NULL)

return b;

else 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 frontBackSplit(Node* source, Node frontRef, Node backRef) {

Node* fast;

Node* slow;

slow = source;

fast = source->next;

while (fast != NULL) {

fast = fast->next;

if (fast != NULL) {

slow = slow->next;

fast = fast->next;

}

}

*frontRef = source;

*backRef = slow->next;

slow->next = NULL;

}

void mergeSort(Node headRef) {

Node* head = *headRef;

Node* a;

Node* b;

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

return;

}

frontBackSplit(head, &a, &b);

mergeSort(&a);

mergeSort(&b);

*headRef = sortedMerge(a, b);

}

// Helper functions to create and print the linked list

void push(Node head_ref, int new_data) {

Node* new_node = (Node*)malloc(sizeof(Node));

new_node->data = new_data;

new_node->next = *head_ref;

*head_ref = new_node;

}

void printList(Node* node) {

while (node != NULL) {

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

node = node->next;

}

}

int main() {

Node* head = NULL;

push(&head, 15);

push(&head, 10);

push(&head, 5);

push(&head, 20);

push(&head, 3);

push(&head, 2);

printf("Linked list before sorting:n");

printList(head);

mergeSort(&head);

printf("nLinked list after sorting:n");

printList(head);

return 0;

}

三、使用快速排序

快速排序是一种分治算法,通常用于数组的排序,但也可以用于链表的排序。快速排序的时间复杂度为O(n log n)在平均情况下,但最坏情况下为O(n^2)。

快速排序的具体步骤如下:

  1. 选择基准:选择链表中的一个节点作为基准。
  2. 分割链表:将链表分成两部分,一部分小于基准,另一部分大于基准。
  3. 递归排序:递归地对两个子链表进行快速排序。

#include <stdio.h>

#include <stdlib.h>

typedef struct Node {

int data;

struct Node* next;

} Node;

Node* getTail(Node* cur) {

while (cur != NULL && cur->next != NULL)

cur = cur->next;

return cur;

}

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

Node* pivot = end;

Node* prev = NULL, * cur = head, * 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;

Node* tmp = cur->next;

cur->next = NULL;

tail->next = cur;

tail = cur;

cur = tmp;

}

}

if ((*newHead) == NULL)

(*newHead) = pivot;

(*newEnd) = tail;

return pivot;

}

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

if (!head || head == end)

return head;

Node* newHead = NULL, * newEnd = NULL;

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

if (newHead != pivot) {

Node* tmp = newHead;

while (tmp->next != pivot)

tmp = tmp->next;

tmp->next = NULL;

newHead = quickSortRecur(newHead, tmp);

tmp = getTail(newHead);

tmp->next = pivot;

}

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

return newHead;

}

void quickSort(Node headRef) {

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

}

// Helper functions to create and print the linked list

void push(Node head_ref, int new_data) {

Node* new_node = (Node*)malloc(sizeof(Node));

new_node->data = new_data;

new_node->next = *head_ref;

*head_ref = new_node;

}

void printList(Node* node) {

while (node != NULL) {

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

node = node->next;

}

}

int main() {

Node* head = NULL;

push(&head, 6);

push(&head, 5);

push(&head, 3);

push(&head, 8);

push(&head, 7);

push(&head, 2);

push(&head, 4);

printf("Linked list before sorting:n");

printList(head);

quickSort(&head);

printf("nLinked list after sorting:n");

printList(head);

return 0;

}

四、对链表节点进行交换

另一种排序链表的方法是直接交换节点,而不是交换节点中的数据。这种方法可以有效避免数据拷贝,提高效率。

交换节点的具体步骤如下:

  1. 选择排序算法:可以使用插入排序、合并排序或快速排序等算法。
  2. 交换节点位置:在排序过程中,直接交换链表节点的位置,而不是节点中的数据。

五、递归和迭代方法

在链表排序中,可以使用递归和迭代两种方法来实现排序算法。递归方法通常更直观,但可能导致栈溢出;迭代方法则更适合处理大规模链表。

递归方法

递归方法适用于合并排序和快速排序等分治算法,可以简化代码实现,提高代码可读性。

迭代方法

迭代方法适用于插入排序和其他简单排序算法,可以避免递归导致的栈溢出问题。

#include <stdio.h>

#include <stdlib.h>

typedef struct Node {

int data;

struct Node* next;

} Node;

// Helper functions to create and print the linked list

void push(Node head_ref, int new_data) {

Node* new_node = (Node*)malloc(sizeof(Node));

new_node->data = new_data;

new_node->next = *head_ref;

*head_ref = new_node;

}

void printList(Node* node) {

while (node != NULL) {

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

node = node->next;

}

}

int main() {

Node* head = NULL;

push(&head, 7);

push(&head, 1);

push(&head, 3);

push(&head, 2);

push(&head, 8);

printf("Linked list before sorting:n");

printList(head);

// Choose and call a sorting function here

// Example: mergeSort(&head);

printf("nLinked list after sorting:n");

printList(head);

return 0;

}

通过选择合适的排序算法,并结合递归和迭代方法,可以有效地对链表进行排序。常见的排序算法包括插入排序、合并排序和快速排序,具体选择取决于链表的规模和排序需求。无论是递归还是迭代方法,都有其优缺点,开发者可以根据具体情况选择合适的方法。

相关问答FAQs:

1. 什么是链表排序?
链表排序是指对链表中的元素进行重新排列,使得链表中的元素按照一定的顺序排列,常见的排序方式包括升序和降序。

2. 如何使用C语言对链表进行排序?
使用C语言对链表进行排序的常见方法是使用插入排序或者快速排序算法。插入排序是通过逐个将未排序的元素插入到已排序的部分中,而快速排序则是通过分治法将链表分割为更小的子链表,然后对子链表进行排序,最后合并子链表得到有序链表。

3. 如何实现C语言链表的升序排序?
要实现链表的升序排序,可以按照以下步骤进行:

  • 首先,将链表分为已排序和未排序两部分,初始时已排序部分只包含链表的头节点,未排序部分包含剩余的节点。
  • 然后,从未排序部分中取出一个节点,将其插入到已排序部分中的正确位置,使得已排序部分仍然保持升序排列。
  • 重复上述步骤,直到未排序部分为空,即所有节点都已经插入到已排序部分中。

请注意,以上的排序方法只是其中一种,具体的实现方式可能会因为链表的结构和需求的不同而有所差异。

文章包含AI辅助创作,作者:Edit1,如若转载,请注明出处:https://docs.pingcode.com/baike/952046

(0)
Edit1Edit1
免费注册
电话联系

4008001024

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