[英]Inserting a node into a linked list in constant-time?
我正在做一項作業,它告訴我假設我有一個帶有 header 和尾節點的單向鏈表。 它要我在 position p 之前插入一個項目 y。 任何人都可以查看我的代碼並告訴我我是否在正確的軌道上? 如果沒有,您能否為我提供任何提示或指示(無雙關語)?
tmp = new Node();
tmp.element = p.element;
tmp.next = p.next;
p.element = y;
p.next = tmp;
我想我可能是錯的,因為我根本沒有使用 header 和尾節點,即使在問題描述中特別提到了它們。 我正在考慮編寫一個 while 循環來遍歷列表,直到它找到 p 並以這種方式解決問題,但這不會是恆定時間,對嗎?
如果遇到算法問題,只需寫下來:
// First we have a pointer to a node containing element (elm)
// with possible a next element.
// Graphically drawn as:
// p -> [elm] -> ???
tmp = new Node();
// A new node is created. Variable tmp points to the new node which
// currently has no value.
// p -> [elm] -> ???
// tmp -> [?]
tmp.element = p.element;
// The new node now has the same element as the original.
// p -> [elm] -> ???
// tmp -> [elm]
tmp.next = p.next;
// The new node now has the same next node as the original.
// p -> [elm] -> ???
// tmp -> [elm] -> ???
p.element = y;
// The original node now contains the element y.
// p -> [y] -> ???
// tmp -> [elm] -> ???
p.next = tmp;
// The new node is now the next node from the following.
// p -> [y] -> [elm] -> ???
// tmp -> [elm] -> ???
您已達到要求的效果,但是它可以提高效率,我敢打賭,您現在就可以了解自己。
寫這樣的東西更清晰:
tmp = new Node();
tmp.element = y;
tmp.next = p;
p = tmp;
如果p不可變,那當然不起作用。 但是,如果p == NULL,則您的算法將失敗。
但是我要說的是,如果您對算法有疑問,只需寫下效果即可。 尤其是對於樹和鏈表,您需要確保所有指針都指向嚴格的方向,否則您會陷入困境。
提示 :僅當位置n = 0或列表的開頭時,插入到鏈表中才是常數。 否則,最壞情況下的復雜度是O(n) 。 這並不是說您不能創建一個合理有效的算法,但是它將始終至少具有線性復雜性。
問題中給出標題和尾部節點的原因是,如果您創建的替換節點碰巧變為標題或尾部,則更新標題和尾部引用。 換句話說,給定的先前節點是標頭或尾部。
在單個LinkedList中,僅將Node添加到列表的開頭或僅使用一個Node創建List都將花費O(1)。 或者,因為他們已經提供了TailNode,並且還在列表末尾插入Node將花費O(1)。
其他所有插入操作將取O(n)。
create a node ptr
ptr->info = item //item is the element to be inserted...
ptr->next = NULL
if (start == NULL) //insertion at the end...
start = ptr
else
temp = ptr
while (temp->next != NULL)
temp = temp->next
end while
end if
if (start == NULL) //insertion at the beginning...
start = ptr
else
temp = start
ptr->info = item
ptr->next = start
start = ptr
end if
temp = start //insertion at specified location...
for (i = 1; i < pos-1; i++)
if (start == NULL)
start = ptr
else
t = temp
temp = temp->next
end if
end for
t->next = ptr->next
t->next = ptr
您不做的是將y插入y之前將p之前的元素鏈接起來。 因此,當在p之前插入y時,現在沒有人指向y(至少不在您顯示的代碼片段中)。
如果您知道必須在其間插入y的元素的位置,則只能以固定時間插入。 如果必須搜索該位置,則永遠不能在單個鏈接列表中插入固定時間。
如何使用已經存在的代碼? LinkedHashMap,LinkedList,LinkedHashSet。 您還可以簽出代碼並從中學習。
整個解釋和 2 個代碼在 Java 中......但很容易將其翻譯成您選擇的任何其他語言。 我確實想幫助你,但我自己是初學者......我仍然使用邏輯,從隊列實現中分享它......我粘貼了兩個代碼,一個在 O(N) 中,另一個包含一個名為 append 的方法這是在 O(1) 現在,解釋
在 class 中用頭節點聲明尾節點
現在在方法 append class 下面的第二個代碼中只看尾指針
案例 1:當 LL 為空時,通常人們會檢查 if (head == null) if if true 然后他們將 head 指向新節點並返回
而我所做的是檢查 if (tail == null) 並且如果它是 true 那么 tail = head = newnode 意味着 tail 和 head 現在都指向要添加的新節點。
CASE 2:當 LL 不為空時等等,哈哈,先聽我說完,我知道你可能會想如果 LL 目前只有 1 個節點怎么辦? 嗯……為此……
這種情況 2 會自動處理它,在情況 1 中它會將頭和尾設置為等於新節點的權利,因此它現在只更改和修改尾節點,保持頭節點不變。
這樣,頭部一直指向第一個節點,尾部不斷更新並指向每次 append function 調用創建的新節點。
希望這個解釋有幫助...
附言。 檢查第 24 行的 O(N) 和第 102 行的 O(1),每次通過 append 方法調用將新節點添加到 LL 時,尾部將指向要添加的新節點。
import java.io.*;
import java.util.*;
public class Solution {
// class Solution is what should be called as the LINKEDLIST class but its ok
Node head; // declaring a head for the LL
class Node { // Node class
int data; // the .data variable
Node ref; // .ref aka .next
Node(int data) { // constructor for initializing the values
this.data = data;
this.ref = null;
}
}
public void append(int data) { // i call 'to join at the end' as append
// O(N)
Node newnode = new Node(data); // new node creation
if (head == null) { // checking is head is null aka None in Py
head = newnode;
return;
}
Node curr = head; // assigning head to a curr node ready for traversal
while (curr.ref != null) { // traversal begins
curr = curr.ref;
} // traversal ends
curr.ref = newnode; // this is the last node where the join happens
}
public void p() { // i name printing function as p()
if (head == null) { // if head is null then print empty
System.out.println("Empty");
return;
}
Node curr = head; // same thing - traversal begins here
while (curr != null) {
System.out.println(curr.data);
curr = curr.ref;
} // by now all data values have been printed out already
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); // scanner class for input
Solution l = new Solution(); // object creating for LL as Solution class name
int numberOfNodes = sc.nextInt(); // input for number of NODEs in LL
for (int i = 0; i < numberOfNodes; i++) { // loop for .data values
int data = sc.nextInt();
l.append(data); // function append call for each (i)
}
l.p(); // finally print func call to display output LL
}
}
class PractGG {
Node head;
Node tail;
class Node {
int data;
Node ref;
Node(int data) {
this.data = data;
this.ref = null;
}
}
public void push(int data) {
Node newnode = new Node(data);
if (head == null) {
tail = head = newnode;
return;
}
newnode.ref = head;
head = newnode;
}
public void append(int data) {
// O(1)
Node newnode = new Node(data);
if (tail == null) {
tail = head = newnode;
return;
}
tail.ref = newnode;
tail = newnode;
}
public void p() {
if (head == null) {
System.out.println("Empty");
}
Node curr = head;
while (curr!=null) {
System.out.print(curr.data + "==>");
curr = curr.ref;
}
System.out.println();
}
public static void main(String[] args) {
PractGG l = new PractGG();
l.append(1);
l.append(2);
l.append(3);
l.p();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.