插入排序链接列表Java
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了插入排序链接列表Java相关的知识,希望对你有一定的参考价值。
我在下面有这个代码,我将一个新的整数插入到一个有序的LinkedList中,但我不认为这是“正确”的做事方式,因为我知道有一个单独的链表,指针指向下一个值和双链表指向下一个和上一个值的指针。我试图使用Nodes来实现以下情况,但Java正在导入这个导入org.w3c.dom.Node(文档对象模型),所以卡住了。
插入案例
- 插入空数组
- 如果要插入的值少于所有值,请在开头插入。
- 如果要插入的值大于所有值,请插入最后一个。
- 如果值小于/大于LL中的某些值,则介于两者之间。
import java.util.*; public class MainLinkedList { public static void main(String[] args) { LinkedList<Integer> llist = new LinkedList<Integer>(); llist.add(10); llist.add(30); llist.add(50); llist.add(60); llist.add(90); llist.add(1000); System.out.println("Old LinkedList " + llist); //WHat if you want to insert 70 in a sorted LinkedList LinkedList<Integer> newllist = insertSortedLL(llist, 70); System.out.println("New LinkedList " + newllist); } public static LinkedList<Integer> insertSortedLL(LinkedList<Integer> llist, int value){ llist.add(value); Collections.sort(llist); return llist; }
}
这可能完全符合您的目的:
使用此代码:
import java.util.*;
public class MainLinkedList {
private static LinkedList<Integer> llist;
public static void main(String[] args) {
llist = new LinkedList<Integer>();
addValue(60);
addValue(30);
addValue(10);
addValue(-5);
addValue(1000);
addValue(50);
addValue(60);
addValue(90);
addValue(1000);
addValue(0);
addValue(100);
addValue(-1000);
System.out.println("Linked List is: " + llist);
}
private static void addValue(int val) {
if (llist.size() == 0) {
llist.add(val);
} else if (llist.get(0) > val) {
llist.add(0, val);
} else if (llist.get(llist.size() - 1) < val) {
llist.add(llist.size(), val);
} else {
int i = 0;
while (llist.get(i) < val) {
i++;
}
llist.add(i, val);
}
}
}
这个方法将以排序的方式管理List中的插入,而不使用Collections.sort(list)
如果我们使用listIterator,那么get的复杂性将是O(1)。
public class OrderedList<T extends Comparable<T>> extends LinkedList<T> {
private static final long serialVersionUID = 1L;
public boolean orderedAdd(T element) {
ListIterator<T> itr = listIterator();
while(true) {
if (itr.hasNext() == false) {
itr.add(element);
return(true);
}
T elementInList = itr.next();
if (elementInList.compareTo(element) > 0) {
itr.previous();
itr.add(element);
System.out.println("Adding");
return(true);
}
}
}
}
@Atrakeur
“每次添加新元素时对所有列表进行排序都不高效”
这是真的,但如果您需要列表始终处于排序状态,那么它实际上是唯一的选择。
“最好的方法是将元素直接插入到必要的位置(在正确的位置)。为此,您可以循环所有位置以查找此数字所属的位置”
这正是示例代码所做的。
“或使用Collections.binarySearch让这个高度优化的搜索算法为您完成这项工作”
二进制搜索是有效的,但仅适用于随机访问列表。因此,您可以使用数组列表而不是链接列表,但随着列表的增长,您必须处理内存副本。如果列表的容量高于实际的元素数(这很常见),您还将消耗比您需要的内存更多的内存。
因此,采用哪种数据结构/方法将在很大程度上取决于您的存储和访问要求。
[edit]实际上,示例代码存在一个问题:它在循环时导致列表的多次扫描。
int i = 0;
while (llist.get(i) < val) {
i++;
}
llist.add(i, val);
对get(i)的调用将遍历列表一次以到达第i个位置。然后对add(i,val)的调用再次遍历它。所以这将非常缓慢。
更好的方法是使用ListIterator遍历列表并执行插入。此接口定义了一个add()方法,该方法可用于在当前位置插入元素。
看看com.google.common.collect.TreeMultiset。
这实际上是一个排序集,允许多个相同值的实例。
对于您要做的事情,这是一个很好的妥协。插入比ArrayList便宜,但您仍然可以获得二进制/树搜索的搜索优势。
链表不是SortedList的更好实现
此外,每次添加新元素时对所有列表进行排序效率不高。最好的方法是将元素直接插入到必要的位置(在正确的位置)。为此,您可以循环所有位置以查找此数字所属的位置,然后插入它,或使用Collections.binarySearch让这个高度优化的搜索算法为您完成此任务。
如果在列表中找到对象,BinarySearch将返回对象的索引(如果需要,可以在此处检查重复项)或( - (插入点) - 1)如果对象未在列表中已经全部(并且插入点是需要放置对象以维护订单的索引)
您必须通过了解订单标准来找到插入数据的位置。
简单的方法是强制搜索插入位置(通过列表,二进制搜索...)。
如果您知道数据的性质,另一种方法是估计插入位置以减少检查次数。例如,如果您插入'Zorro'并且列表按字母顺序排列,您应该从列表的后面开始...或估计您的信件可能在哪里(可能在结尾)。如果您知道它们的来源以及它们的分布方式,这也适用于数字。这称为插值搜索:http://en.wikipedia.org/wiki/Interpolation_search
还要考虑批量插入:如果快速插入大量数据,可以考虑一次性进行多次插入,之后只进行一次排序。
你可以简单地在log(N)时间复杂度中做到这一点。无需遍历所有值。您可以使用二进制搜索将值添加到已排序的链接列表。只需在该函数的上限位置添加值。检查代码......你可能会更好地理解。
public static int ubound(LinkedList<Integer> ln, int x) {
int l = 0;
int h = ln.size();
while (l < h) {
int mid = (l + h) / 2;
if (ln.get(mid) <= x) l = mid + 1;
else h = mid;
}
return l;
}
public void solve()
{
LinkedList<Integer> ln = new LinkedList<>();
ln.add(4);
ln.add(6);
ln.add(ubound(ln, 5), 5);
out.println(ln);
}
输出:[4,5,6]
您可以在以下网址了解二进制搜索:https://www.topcoder.com/community/data-science/data-science-tutorials/binary-search/
以上是关于插入排序链接列表Java的主要内容,如果未能解决你的问题,请参考以下文章