以下原理及实现均为个人理解,如有错误或更优解,欢迎留言指正!
排序算法概述
盗个图
转自:https://www.cnblogs.com/onepixel/articles/7674659.html
排序算法复杂度
由于是链表排序,首先定义链表节点数据结构
common.h
typedef struct Node LNode;
struct Node {
int data;
LNode *next;
LNode *prev;
};
备注:以下排序算法默认由小到大排序
链表排序需要注意保证链表节点直接的连续性
- 直接插入排序
算法简介
- 第一个链表节点,可以认为是已排序好;
- 从第二个节点开始进行排序操作,逐一向前遍历,对比节点值大小,遍历至第一个比它的值小的节点,把待排序节点插入到该节点后面;
- 依次对后续所有节点重复第2步操作,直至操作到最后一个节点。
算法实现
LNode* insert_sort(LNode *p) { if(NULL == p) return p; LNode *tmp = NULL; //指向待排序节点,用于节点插入 LNode *q = p, *t = q->next;// q指向待排序节点的前一个节点,t指向待排序节点 while(t) { if(q->data < t->data) { tmp = t; t = t->next; if(t) { t->prev = q; } q->next = t; while(q && (q->data < tmp->data)) { q = q->prev; } if(q) { tmp->next = q->next; q->next->prev = tmp; q->next = tmp; tmp->prev = q; } else { tmp->next = p; tmp->prev = NULL; p->prev = tmp; p = tmp; } if(t) { q = t->prev; } } else { t = t->next; q = q->next; } } return p; }
- 归并排序
算法简介
归并排序采用分治思想,首先使其子序列成为有序序列,然后再对子序列进行归并。
递归实现:
- 首先把链表分割为两个子链表(采用快慢指针找到链表中间节点),递归该分割过程,直至子链表只包含一个节点为止;
- 创建一个新的链表节点,指向排序好的链表;对分割得到的两个子链表逐一遍历对比,值小的节点插入到新链表后面;
- 两个子链表归并完成,且已完成对其排序,返回链表头指针给上层递归。
算法实现
LNode *list_split(LNode *head) //分割链表,返回后一个子链表的头指针
{
if(NULL == head)
{
return head;
}
LNode *tmp = head;
LNode *slow = head, *fast = head; //快慢指针找到原链表的中间节点
while(fast)
{
fast = fast->next;
if(fast)
{
fast = fast->next;
}
if(NULL == fast)
{
break;
}
slow = slow->next;
}
tmp = slow;
slow = slow->next;//中间节点的下一个节点作为第二个子链表的头节点
tmp->next = NULL; //保证每个子链表尾指针都指向NULL
return slow;
}
LNode* merge(LNode *head1, LNode *head2)//对两个链表进行归并,合为一个有序链表
{
if(NULL == head1) return head2;
if(NULL == head2) return head1;
LNode head; //定义一个有序链表的头节点
LNode *tail = &head;
while(head1 && head2)
{
if(head1->data < head2->data) //将小节点插入到有序链表后
{
tail->next = head1;
head1 = head1->next;
}
else
{
tail->next = head2;
head2 = head2->next;
}
tail = tail->next;
}
if(head1) //剩下的节点要保证连接到有序链表后
{
tail->next = head1;
}
if(head2)
{
tail->next = head2;
}
return head.next; //返回有序链表的头指针
}
LNode* merge_sort(LNode *head) //归并排序入口函数
{
if(NULL == head || NULL == head->next) //递归分割链表,直至子链表只包含一个节点为止
{
return head;
}
LNode *head1 = head; //第一个子链表头指针即链表头指针
LNode *head2 = list_split(head); //第二个子链表头指针为中间节点的下一个节点
head1 = merge_sort(head1); //递归第一个子链表
head2 = merge_sort(head2); //递归第二个子链表
return merge(head1, head2); //归并,并返回排序后链表的头指针
}
今天的文章链表排序算法_八种基本排序及其时间复杂度[通俗易懂]分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/69386.html