您的位置:首页 > 其它

在单链表上实现插入排序

2016-09-17 20:10 323 查看

问题

给单链表排序(升序排列,要保持稳定性),要求通过改变结点的next指针从而改变结点的位置,而不是只交换结点的值来使得其有序!时间复杂度为O(N^2),空间复杂度为O(1)。已知链表结点的实现如下:

struct ListNode
{
int value;
ListNode* next;
ListNode(int v)
: value(v), next(NULL) {}
};


思路

这里很明显就是要我们做插入排序了,当然,冒泡也不是不可以,只是冒泡写起来麻烦,且性能是最差的。

插入排序怎么写呢?

这个算法的思想是这样的:

1. 维护两部分,一是已排序的部分,一是待排序的部分;

2. 一开始已排序部分为NULL;

3. 每次取出待排序部分的第一个元素A,和已排序的部分逐个比较(从头往后或从后往前都可以,不过单链表只能够从头往后比较),找到第一个大于A的元素B;

4. 将A插在B的前面一个位置(这时需要注意了,如果B原来是链表头,那么A将变成新的链表头,此时要记得更新链表头指针)。

代码

#include <iostream>
#include <string>
using namespace std;

struct ListNode { int value; ListNode* next; ListNode(int v) : value(v), next(NULL) {} };

ListNode* sortList(ListNode* head) {
// 注意这样写,是不需要额外判断head是否为NULL的
ListNode *newHead = NULL, *toInsert = head;
while (toInsert != NULL) {
ListNode *current = newHead, *last = NULL, *next = toInsert->next;
// 从头往后找到第一个大于toInsert->value的元素
while (current != NULL && current->value <= toInsert->value) {
last = current;
current = current->next;
}

if (last == NULL) {
// 如果比任何已排序的数字都要小,那么就成为新的头部
toInsert->next = newHead;
newHead = toInsert;
} else {
// 否则插入到last的后面
toInsert->next = last->next;
last->next = toInsert;
}

toInsert = next;
}
return newHead;
}

// 打印链表
void display(ListNode* head) {
while (head != NULL) {
cout << head->value << ' ';
head = head->next;
}
cout << endl;
}

int main() {
ListNode* head = new ListNode(5);
head->next = new ListNode(4);
head->next->next = new ListNode(3);
head->next->next->next = new ListNode(2);
head->next->next->next->next = new ListNode(1);
display(head);

ListNode* head2 = sortList(head);
display(head2);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: