无序链表排序_双向链表排序算法
2023-06-13 09:14:59 时间
需求
给定一个无序的链表,输出有序的链表。
分析
链表排序比较特殊,由于不连续的性质,所以在进行排序的时候要引入外排思想,因此归并排序或者多路归并就成为了排序的选择。 归并排序分为拆分、合并两个阶段: 1. 拆分 需要找出链表中间节点,并根据中间节点拆分成两个独立的链表,递归直到拆分成单个节点为止。 2. 合并 由于此时每个链表都为单节点,所以对于拆分的两个子链表实质上是有序链表合并问题。
代码
下面是示例代码
private class Node {
int value;
Node next;
}
private Node getRandomList(int length)
{
Node node = new Node();
int randomNum = (int) ((Math.random() * 100) % 100);
node.value = randomNum;
Node head = node;
for(int i = 0; i < length; i++)
{
randomNum = (int) ((Math.random() * 100) % 100);
Node temp = new Node();
temp.value = randomNum;
node.next = temp;
node = temp;
}
return head;
}
private Node getMiddleNode(Node head)
{
Node index1 = head;
Node index2 = head;
while(index2.next != null && index2.next.next != null)
{
index1 = index1.next;
index2 = index2.next.next;
}
return index1;
}
private Node mergeSort(Node head)
{
if(head.next == null)
return head;
Node middelNode = getMiddleNode(head);
Node head1 = head;
Node head2 = middelNode.next;
middelNode.next = null;
head1 = mergeSort(head1);
head2 = mergeSort(head2);
Node currenthead = mergeSequentialList(head1, head2);
return currenthead;
}
private Node mergeSequentialList(Node head1, Node head2)
{
if(head1 == null)
return head2;
if(head2 == null)
return head1;
Node currentNode = null;
if(head1.value < head2.value)
{
head1.next = mergeSequentialList(head1.next, head2);
currentNode = head1;
}
else
{
head2.next = mergeSequentialList(head1, head2.next);
currentNode = head2;
}
return currentNode;
}
private int outputListValue(Node list, StringBuffer bf) {
// TODO Auto-generated method stub
int i = 0;
while(list.next != null)
{
bf.append(list.value + "-");
i++;
list = list.next;
}
return i;
}
public void main()
{
Node list = getRandomList(50);
list = mergeSort(list);
StringBuffer bf = new StringBuffer();
int count = outputListValue(list, bf);
String result = bf.toString();
}
复杂度
对于中间节点的查找,可以使用两指针不同步调方式,查找的时间复杂度为O(n)。 对于两个有序子链表合并,递归深度为最短链表深度,时间复杂度为O(n)。 由于归并排序会调用logn次,所以最终的时间复杂度为(2n)logn = O(nlogn)。
总结
无序链表排序考察的知识点比较多,首先要深刻理解归并排序的思想与应用场景,其次算法中也运用到了链表中间节点查找、两个有序链表归并等单算法,并且也要考虑单算法其中的细节。整体算法难度比较难。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/183150.html原文链接:https://javaforall.cn
【
相关文章
- 【NLP基础】英文关键词抽取RAKE算法
- 数据结构与算法(三):双向链表[通俗易懂]
- 驱动开发:内核中的链表与结构体
- 剑指offer No.36 两个链表的第一个公共结点
- 《算法竞赛进阶指南》0x13 链表与邻接表
- Go 数据结构和算法篇(一):链表
- LeetCode 82:删除排序链表中的重复元素 II
- 【拿捏链表(Ⅱ)】—Leetcode删除排序链表中的重复元素
- 【Redis】Redis 有序集合 Zset 操作 ( Zset 有序集合数据结构 | 普通链表 | 跳跃表 )
- LeetCode每日一题之817题链表组件
- 算法-从尾到头打印链表详解编程语言
- 算法-复杂链表的复制详解编程语言
- java 数据结构与算法—链表详解编程语言
- 复杂链表的复制算法详解编程语言
- 算法练习之合并两个有序链表, 删除排序数组中的重复项,移除元素,实现strStr(),搜索插入位置,无重复字符的最长子串详解编程语言
- 掌握Linux内核中链表的使用(linux内核链表使用)
- MySQL查询实现三级链表查询技巧(mysql 三级链表查询)
- C#数据结构与算法揭秘三链表
- C#数据结构与算法揭秘四双向链表
- C语言实现带头结点的链表的创建、查找、插入、删除操作