单链表的排序算法
1、插入排序
插入排序可以通过直接交换节点得到。
/*
功能:插入排序
参数:传入链表头指针作为参数,返回排序后的头指针
说明:时间复杂度O(n^2),空间复杂度O(1)
第一步:选择插入的位置;
第二步:如果在已排序的链表的尾部,则直接加入到尾部,否则,插入到选好的位置。注意:需要保存前驱节点。
*/
func InsertSort(head *ListNode) *ListNode {
if head == nil || head.Next == nil { return head }
var pre, p, start, end *ListNode
p, start, end, pre = head.Next, head, head, head
var next *ListNode
for p != nil {
next, pre = p.Next, start
for next != p && p.Val >= next.Val {
next = next.Next
pre = pre.Next
}
// 追加到已经排序的队尾
if next == p {
pend = p
} else {
pend.Next = p.Next
p.Next = next
pre.Next = p
}
p = pend.Next
}
return head
}
2、选择排序
/*
功能:选择排序(选择未排序序列中的最值,然后放到已排序的最前面或最后面,只交换节点的值)
参数:输入链表的头指针,返回排序后的头指针
说明:时间复杂度O(n^2),空间复杂度O(1)
*/
Node *SelectSort(Node *phead) {
if(phead == NULL || phead->next == NULL) return phead;
Node *pend = phead;
while(pend->next != NULL) {
Node *minNode = pend->next;
Node *p = minNode->next;
while(p != NULL) {
if(p->val < minNode->val)
minNode = p;
p = p->next;
}
swap(minNode->val, pend->val);
pend = pend->next;
}
return phead;
}
3、快速排序
/*
功能:快速排序,链表指向下一个元素的特性,partition是选择左闭合区间
第一步,partiton,因为链表不支持随机访问元素,因此partiton中选取第一个节点值作为基准
第二步,排序
参数:输入链表头指针,输出排序后的头指针
说明:平均时间复杂度O(nlogn),空间复杂度O(1)
*/
Node *Partition(Node *low, Node *high) {
//左闭合区间[low, high)
int base = low->val;
Node *location = low;
for(Node *i = low->next; i != high; i = i->next) {
if(i->val > base) {
location = location->next;
swap(location->val, i->val);
}
}
swap(low->val, location->val);
return location;
}
void QuickList(Node *phead, Node *tail) {
//左闭合区间[phead, tail)
if(phead != tail && phead->next != tail) {
Node *mid = Partition(phead, tail);
QuickList(phead, mid);
QuickList(mid->next, tail);
}
}
Node *QuickSort(Node *phead) {
if(phead == NULL || phead->next == NULL) return phead;
QuickList(phead, NULL);
return phead;
}
4、归并排序
/*
功能:归并排序,交换链表节点
第一步:先写归并函数;第二步:利用快慢指针找到链表中点,然后递归对子链进行排序
参数:输出链表的头指针,输出排序后的头指针
说明:时间复杂度O(nlogn),空间复杂度O(1)。归并排序应该算是链表排序中最佳的选择,保证最好和最坏的时间复杂度都是O(nlogn),而且在将空间复杂度由数组中O(n),降到链表中的O(1)
*/
Node *merge(Node *phead1, Node *phead2) {
if(phead1 == NULL) return phead2;
if(phead2 == NULL) return phead1;
Node *res, *p;
if(phead1->val < phead2->val) {
res = phead1;
phead1 = phead1->next;
} else {
res = phead2;
phead2 = phead2->next;
}
p = res;
while(phead1 != NULL && phead2 != NULL) {
if(phead1->val < phead2->val) {
p->next = phead1;
phead1 = phead1->next;
} else {
p->next = phead2;
phead2 = phead2->next;
}
p = p->next;
}
if(phead1 != NULL) p->next = phead1;
else if(phead2 != NULL) p->next = phead2;
return res;
}
Node *MergeSort(Node *phead) {
if(phead == NULL || phead->next == NULL) return phead;
Node *fast = phead;
Node *slow = phead;
while(fast->next != NULL && fast->next->next != NULL) {
fast = fast->next->next;
slow = slow->next;
}
fast = slow;
slow = slow->next;
fast->next = NULL;
fast = MergeSort(phead);
slow = MergeSort(slow);
return merge(fast, slow);
}
最后更新于