簡體   English   中英

在恆定時間內將節點插入鏈表?

[英]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) 現在,解釋

  1. 在 class 中用頭節點聲明尾節點

  2. 現在在方法 append class 下面的第二個代碼中只看尾指針

  3. 案例 1:當 LL 為空時,通常人們會檢查 if (head == null) if if true 然后他們將 head 指向新節點並返回

    而我所做的是檢查 if (tail == null) 並且如果它是 true 那么 tail = head = newnode 意味着 tail 和 head 現在都指向要添加的新節點。

  4. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM