制作简单网页的步骤杭州专业seo服务公司
对一个单向的无序链表进行排序,通常可以采用以下几种排序算法:插入排序、归并排序、快速排序等。对于链表来说,归并排序是一个特别适合的选择,因为它是一个稳定的排序算法,不需要额外的空间,并且具有较好的时间复杂度。链表的节点在排序时可以直接调整指针,因此比数组更适合使用归并排序。
归并排序的思路:
1. 分割:将链表从中间分成两个部分。
2. 递归排序:递归地对每个部分进行排序。
3. 合并:将两个已排序的子链表合并成一个有序链表。
步骤:
1. 使用快慢指针找到链表的中点,并将链表分成两部分。
2. 递归排序这两部分链表。
3. 合并两个已排序的链表。
#include
using namespace std;// 定义单链表节点
struct ListNode {int val;ListNode* next;ListNode(int x) : val(x), next(nullptr) {}
};// 合并两个有序链表
ListNode* merge(ListNode* l1, ListNode* l2) {// 创建一个虚拟头结点ListNode* dummy = new ListNode(0);ListNode* current = dummy;// 合并两个链表while (l1 != nullptr && l2 != nullptr) {if (l1->val < l2->val) {current->next = l1;l1 = l1->next;} else {current->next = l2;l2 = l2->next;}current = current->next;}// 如果有剩余的节点,直接连接if (l1 != nullptr) {current->next = l1;} else if (l2 != nullptr) {current->next = l2;}return dummy->next;
}// 寻找链表的中点
ListNode* findMiddle(ListNode* head) {if (head == nullptr) return nullptr;ListNode* slow = head;ListNode* fast = head;while (fast != nullptr && fast->next != nullptr) {slow = slow->next;fast = fast->next->next;}return slow;
}// 归并排序
ListNode* mergeSort(ListNode* head) {if (head == nullptr || head->next == nullptr) {return head; // 如果链表为空或只有一个元素,返回本身}// 寻找中点并分割链表ListNode* middle = findMiddle(head);ListNode* secondHalf = middle->next;middle->next = nullptr; // 断开链表// 递归排序两个子链表ListNode* left = mergeSort(head);ListNode* right = mergeSort(secondHalf);// 合并两个已排序的链表return merge(left, right);
}// 用于打印链表
void printList(ListNode* head) {ListNode* current = head;while (current != nullptr) {cout << current->val << " -> ";current = current->next;}cout << "null" << endl;
}// 主函数,测试代码
int main() {// 构造链表ListNode* head = new ListNode(4);head->next = new ListNode(2);head->next->next = new ListNode(1);head->next->next->next = new ListNode(3);cout << "Original list: ";printList(head);// 排序链表head = mergeSort(head);cout << "Sorted list: ";printList(head);return 0;
}
详细解释:
1. ListNode 结构体:定义了链表节点,包含一个整数值 `val` 和一个指向下一个节点的指针 `next`。
2. merge 函数:负责合并两个已排序的链表。通过比较两个链表的节点值,逐个将较小的节点加入到新的链表中,直到其中一个链表为空,最后将另一个链表剩余的部分接到合并链表的末尾。
3. findMiddle 函数:使用快慢指针找到链表的中点。快指针每次走两步,慢指针每次走一步。当快指针到达末尾时,慢指针刚好到达链表的中点。
4. mergeSort 函数:递归实现归并排序。首先找到链表的中点,然后递归地对左右两个子链表进行排序,最后将两个已排序的子链表合并。
5. printList 函数:用于打印链表,方便查看排序前后的结果。
复杂度分析:
时间复杂度:每次递归都将链表分为两半,递归深度为 `O(log n)`,在每一层递归中合并链表的时间是 `O(n)`,因此总的时间复杂度为 `O(n log n)`。
空间复杂度:归并排序需要递归栈的空间,递归的最大深度为 `O(log n)`,因此空间复杂度为 `O(log n)`。