小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
以下是数组快速排序的典型递归实现。该实现使用最后一个元素作为枢轴。
int partition (int arr[], int l, int h)
{
int x = arr[h];
int i = (l - 1);
for (int j = l; j <= h- 1; j++)
{
if (arr[j] <= x)
{
i++;
swap (&arr[i], &arr[j]);
}
}
swap (&arr[i + 1], &arr[h]);
return (i + 1);
}
void quickSort(int A[], int l, int h)
{
if (l < h)
{
int p = partition(A, l, h); /* Partitioning index */
quickSort(A, l, p - 1);
quickSort(A, p + 1, h);
}
}
我们可以对链表使用相同的算法吗?
以下是双向链表的 C++ 实现。思路很简单,我们先找出指向最后一个节点的指针。一旦我们有了指向最后一个节点的指针,我们就可以使用指向链表的第一个和最后一个节点的指针对链表进行递归排序,类似于上面我们传递第一个和最后一个数组元素的索引的递归函数。链表的分区函数也类似于数组的分区。它不返回枢轴元素的索引,而是返回一个指向枢轴元素的指针。在下面的实现中,quickSort()只是一个包装函数,主要的递归函数是_quickSort(),类似于quickSort()的数组实现。
#include <bits/stdc++.h>
using namespace std;
class Node
{
public:
int data;
Node *next;
Node *prev;
};
void swap ( int* a, int* b )
{ int t = *a; *a = *b; *b = t; }
Node *lastNode(Node *root)
{
while (root && root->next)
root = root->next;
return root;
}
Node* partition(Node *l, Node *h)
{
int x = h->data;
Node *i = l->prev;
for (Node *j = l; j != h; j = j->next)
{
if (j->data <= x)
{
i = (i == NULL)? l : i->next;
swap(&(i->data), &(j->data));
}
}
i = (i == NULL)? l : i->next;
swap(&(i->data), &(h->data));
return i;
}
void _quickSort(Node* l, Node *h)
{
if (h != NULL && l != h && l != h->next)
{
Node *p = partition(l, h);
_quickSort(l, p->prev);
_quickSort(p->next, h);
}
}
void quickSort(Node *head)
{
Node *h = lastNode(head);
_quickSort(head, h);
}
void printList(Node *head)
{
while (head)
{
cout << head->data << " ";
head = head->next;
}
cout << endl;
}
void push(Node** head_ref, int new_data)
{
Node* new_node = new Node;
new_node->data = new_data;
new_node->prev = NULL;
new_node->next = (*head_ref);
if ((*head_ref) != NULL) (*head_ref)->prev = new_node ;
(*head_ref) = new_node;
}
/* Driver code */
int main()
{
Node *a = NULL;
push(&a, 5);
push(&a, 20);
push(&a, 4);
push(&a, 3);
push(&a, 30);
cout << "排序前的链表 \n";
printList(a);
quickSort(a);
cout << "排序后的链表 \n";
printList(a);
return 0;
}
输出 :
排序前的链表
30 3 4 20 5
排序后的链表
3 4 5 20 30
时间复杂度: 上述实现的时间复杂度与数组 QuickSort() 的时间复杂度相同。在最坏情况下需要 O(n^2) 时间,在平均和最佳情况下需要 O(nLogn) 时间。最坏的情况发生在链表已经排序时。
我们可以为链表实现随机快速排序吗?
只有当我们可以选择一个固定点作为枢轴时(如上述实现中的最后一个元素),才能为链表实现快速排序。随机快速排序不能通过选择随机主元有效地为链表实现。
🥇 往期优质文章
数据结构双向链表的介绍和插入 | 第一套
数据结构删除双向链表中的节点 | 第二套
数据结构反转双向链表 | 第三套
📣尾注: 想要获取更多数据结构相关的知识,你可以关注我:海拥,我希望你觉得这篇文章有帮助。
如果你看到这里,感谢你的阅读 :)
💌 欢迎大家在评论区提出意见和建议!💌
如果你真的从这篇文章中学到了一些新东西,喜欢它,收藏它并与你的小伙伴分享。🤗最后,不要忘了❤或📑支持一下哦。