用c语言选取一个合适的数据结构存储一批数据,能对数据进行插入和删除操作,还能分别用三种不同的排序算法对这些数据进行排序
时间: 2024-02-22 12:57:52 浏览: 76
可以使用链表来存储一批数据,并可以对数据进行插入和删除操作。链表的头结点存储链表的长度,每个节点存储一个数据元素。
在链表中,可以使用插入排序、快速排序和归并排序等算法对数据进行排序。这里简单介绍一下这三种排序算法的实现。
1. 插入排序
插入排序的思路是,将数组分为已排序区间和未排序区间,每次取未排序区间的第一个元素,插入已排序区间的合适位置。在链表中,可以从头节点开始遍历链表,将未排序节点插入已排序区间的合适位置。
```c
void insertion_sort(struct ListNode* head) {
if (!head || !head->next) {
return;
}
struct ListNode* sorted = head->next;
head->next = NULL;
while (sorted) {
struct ListNode* node = sorted;
sorted = sorted->next;
struct ListNode* cur = head;
while (cur->next && cur->next->val < node->val) {
cur = cur->next;
}
node->next = cur->next;
cur->next = node;
}
}
```
2. 快速排序
快速排序的思路是,在数组中选择一个基准元素,将数组分为左右两个部分,左边部分的元素都小于基准元素,右边部分的元素都大于基准元素,然后对左右两个部分分别进行快速排序。在链表中,可以将链表分为左右两个部分,使用快慢指针找到链表的中间节点,然后对左右两个部分分别进行快速排序。
```c
struct ListNode* partition(struct ListNode* head, struct ListNode* end, struct ListNode** new_head, struct ListNode** new_end) {
struct ListNode* pivot = end;
struct ListNode* prev = NULL;
struct ListNode* cur = head;
struct ListNode* tail = pivot;
while (cur != pivot) {
if (cur->val < pivot->val) {
if (!(*new_head)) {
*new_head = cur;
}
prev = cur;
cur = cur->next;
} else {
if (prev) {
prev->next = cur->next;
}
struct ListNode* tmp = cur->next;
cur->next = NULL;
tail->next = cur;
tail = cur;
cur = tmp;
}
}
if (!(*new_head)) {
*new_head = pivot;
}
*new_end = tail;
return pivot;
}
struct ListNode* quick_sort_helper(struct ListNode* head, struct ListNode* end) {
if (!head || head == end) {
return head;
}
struct ListNode* new_head = NULL;
struct ListNode* new_end = NULL;
struct ListNode* pivot = partition(head, end, &new_head, &new_end);
if (new_head != pivot) {
struct ListNode* tmp = new_head;
while (tmp->next != pivot) {
tmp = tmp->next;
}
tmp->next = NULL;
new_head = quick_sort_helper(new_head, tmp);
tmp = get_tail(new_head);
tmp->next = pivot;
}
pivot->next = quick_sort_helper(pivot->next, new_end);
return new_head;
}
void quick_sort(struct ListNode* head) {
if (!head || !head->next) {
return;
}
struct ListNode* tail = get_tail(head);
head = quick_sort_helper(head, tail);
}
```
3. 归并排序
归并排序的思路是,将数组分为两个部分,分别对左右两个部分进行归并排序,然后将左右两个部分合并。在链表中,可以使用快慢指针将链表分为两个部分,然后分别对左右两个部分进行归并排序,然后将左右两个部分合并。
```c
struct ListNode* merge(struct ListNode* l1, struct ListNode* l2) {
struct ListNode dummy = {0};
struct ListNode* cur = &dummy;
while (l1 && l2) {
if (l1->val < l2->val) {
cur->next = l1;
l1 = l1->next;
} else {
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
if (l1) {
cur->next = l1;
}
if (l2) {
cur->next = l2;
}
return dummy.next;
}
struct ListNode* merge_sort_helper(struct ListNode* head) {
if (!head || !head->next) {
return head;
}
struct ListNode* slow = head;
struct ListNode* fast = head->next;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
struct ListNode* right = slow->next;
slow->next = NULL;
struct ListNode* left = merge_sort_helper(head);
right = merge_sort_helper(right);
return merge(left, right);
}
void merge_sort(struct ListNode* head) {
if (!head || !head->next) {
return;
}
head = merge_sort_helper(head);
}
```
上面的代码中,`struct ListNode` 表示链表节点的结构体,包含了一个整型变量 `val` 和一个指向下一个节点的指针 `next`。`get_tail` 函数用于获取链表的尾节点,`partition` 函数用于将链表分为左右两个部分,`merge` 函数用于将两个有序链表合并为一个有序链表。
阅读全文