Java 删除linkedlist中元素的所有引用
为了理解数据结构,我开始用java实现它们。Java 删除linkedlist中元素的所有引用,java,linked-list,implementation,Java,Linked List,Implementation,为了理解数据结构,我开始用java实现它们。deleteAll的时间复杂度将是O(n+n^2)。如何改进deleteAll方法 /* * Singly linked list */ package linkedlisttest; class Node { int data; Node next; public Node(int data) { this.data = data; } } class LinkedList {
deleteAll
的时间复杂度将是O(n+n^2)
。如何改进deleteAll
方法
/*
* Singly linked list
*/
package linkedlisttest;
class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
}
}
class LinkedList {
Node head;
int size;
/**
*
* @param data element to add to list
* Time Complexity : O(n)
*/
public void add(int data) {
if (head == null) {
head = new Node(data);
size += 1;
return;
}
Node current = head;
while (current.next != null) {
current = current.next;
}
current.next = new Node(data);
size += 1;
}
/**
*
* @return size of list
* Time Complexity: O(1)
* This is because we use a class
* variable size to keep track of size of linked list
*/
public int getSize() {
return size;
}
/**
*
* @param data element to insert
* @param index position at which to insert the element (zero based)
* Time Complexity : O(n)
*/
public void add(int data, int index) {
if (index > getSize()) {
return; // invalid position
}
Node current = head; //iterate through whole list
int pos = 0;
Node newNode = new Node(data);
if (index == 0) // special case, since its a single reference change!
{
newNode.next = head;
head = newNode; // this node is now the head
size += 1;
return;
}
while (current.next != null) {
if (pos == index - 1) {
break;
}
pos++;
current = current.next;
}
// These are 2 reference changes, as compared to adding at index 0
newNode.next = current.next; // here we are changing a refernce
current.next = newNode; // changing a reference here as well
size += 1;
}
/**
* Find the first occurrence of an element
* @param data element to find
* @return index at which element is found , -1 if not exist
* Time Complexity: O(n)
*/
public int find(int data) {
Node current = head;
int pos = 0;
int index = -1;
if(head == null) { //empty list
return index;
}
while(current != null) {
if (current.data == data) {
index = pos;
break;
}
pos++;
current = current.next;
}
return index;
}
/**
* Delete the first occurrence of data
* @param data element to delete
* Time complexity : O(n)
*/
public void delete(int data) {
Node current = head;
if (head == null) { // list is empty
return;
}
if(head.data == data) { // if we want to delete the head , make next node head
head = head.next;
size -= 1;
return;
}
while(current.next != null) {
if (current.next.data == data) {
current.next = current.next.next;
size -= 1;
return;
}
current = current.next;
}
}
/**
* Delete all occurrences of data
* @param data element to delete
*
*/
public void deleteAll(int data) {
Node current = head;
if (head == null) { // list is empty
return;
}
//while loop to delete consecutive occurances of data
while(head.data == data) { // if we want to delete the head , make next node head
head = head.next;
size -= 1;
}
while(current.next != null) {
//while loop to delete consecutive occurances of data
while (current.next.data == data) {
current.next = current.next.next;
size -= 1;
}
current = current.next;
}
}
public void reverse() {
}
/**
* Prints the whole linked list
* Time Complexity : O(n)
*/
public void print() {
if(head == null) { //list is empty
return;
}
Node current = head;
while (current.next != null) {
System.out.print(current.data + "->");
current = current.next;
}
System.out.print(current.data + "\n");
}
}
public class LinkedListTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
LinkedList lt = new LinkedList();
lt.print();
lt.add(3);
lt.add(5);
lt.add(6);
lt.print();
lt.add(4, 1);
lt.print();
lt.add(4, 7);// 7 is an invalid index
lt.add(8, 3);
lt.add(8, 4);
lt.print();
System.out.println("Position : " + lt.find(8));
lt.delete(5);
lt.print();
lt.deleteAll(8);
lt.print();
System.out.println("Size : " + lt.getSize());
}
}
请注意,Java中的所有内容都是引用,但这些基本类型除外。因此,
当前的
仍然停留在原始的头部
没有必要将连续发生的事件视为特殊情况。使用O(n)
-线性复杂度在链表中进行简单的迭代和判断将完全满足您的要求
此外,嵌套循环并不一定意味着它一定要花费O(n^2)。如果每次移动current
,它仍然会在线性时间内遍历链表
另一个个人建议:如果在处理链表时需要编写类似node.next.next的东西,那么是时候设置另一个引用或重构代码了。实现的时间复杂性是
O(n)
,而不是您认为的O(n+n^2)
。
尽管嵌套循环是O(n^2)的常见符号,但情况并非总是如此。
重要的一点是迭代次数。
就你而言,
如果在嵌套循环中执行k
步骤,
这将外部循环中的剩余步骤减少k
。
总的来说,
您仍将采取n
步骤以达到目的
但是您的实现有一些bug,
还可以改进:
- 错误:您分配了
,但是如果current=head
,它将被删除,并且head.data==data
仍将指向它current
- 不需要嵌套循环。在对头部进行特殊处理后,您可以简单地跟踪节点并删除匹配项
public void deleteAll(int data) {
while (head != null && head.data == data) {
head = head.next;
size -= 1;
}
if (head == null) {
return;
}
Node current = head;
while (current.next != null) {
if (current.next.data == data) {
current.next = current.next.next;
size -= 1;
} else {
current = current.next;
}
}
}
顺便说一下,头部的特殊处理可能有点烦人。
一个优雅的替代方法是创建一个指向头部的虚拟对象
:
public void deleteAll(int data) {
Node dummy = new Node();
dummy.next = head;
Node current = dummy;
while (current.next != null) {
if (current.next.data == data) {
current.next = current.next.next;
size -= 1;
} else {
current = current.next;
}
}
head = dummy.next;
}
如果此代码工作正常,那么此问题与堆栈溢出无关,但可能对我们的姐妹站点有好处。感谢全面的解释和代码示例。
}否则{current=current.next;}
是这里的关键,我早期的实现基于delete,它总是迭代到下一个节点