簡體   English   中英

在單鏈接列表中添加雙鏈接列表節點

[英]Add Doubly Linked List Node in Singly Linked List

給定單鏈表: 1 -> 2 -> 3 -> 4 -> 5 -> null
修改中間元素為雙鏈表節點
這里中間元素是3
3 -> next應指向4
3 -> prev應該指向1

有人可以建議怎么做嗎? 面試官給我提示use interface 但我不知道怎么做。
我必須遍歷此鏈接列表並打印所有節點,當它到達中間時,打印next和prev指向的位置,然后打印到列表末尾。
Expected output1, 2, Middle: 3, Prev: 1, Next: 4, 5

我在添加中間節點時遇到問題。

根據定義 ,單鏈列表僅包含單鏈節點,而雙鏈列表僅包含雙鏈節點。 除此以外。 兩者都不是。

根據定義 ,雙向鏈接列表的字段prev 必須指向上一個元素。

無論您打算建造什么。 沒有明確說明。 因此,如果您在采訪中真的被問到了這一點(並且沒有誤解這個問題-也許他想讓您指出ghis 違反了界面?)這是http://thedailywtf.com/的代碼恐怖故事的一種情況-“無能的面試官”。

因此,這是“ 有效的 ”,但是如果希望在采訪中得到回答,那就太麻煩了。

鏈表

public class LinkedList {

    public interface Linkable<V, L extends Linkable> {
        V getValue();
        L getNext();
        void setNext(L link);
    }

    public static class Node implements Linkable<Integer, Linkable> {
        int value;
        Linkable next;

        Node(int value) {
            this.value = value;
        }

        @Override
        public Integer getValue() {
            return value;
        }

        @Override
        public Linkable getNext() {
            return next;
        }

        @Override
        public void setNext(Linkable link) {
            this.next = link;
        }
    }

    private Linkable head;

    public boolean isEmpty() {
        return this.head == null;
    }

    public Linkable getHead() {
        return head;
    }

    public void add(int v) {
        Node next = new Node(v);
        if (isEmpty()) {
            this.head = next;
        } else {
            Linkable tmp = this.head;
            while (tmp.getNext() != null) {
                tmp = tmp.getNext();
            }
            tmp.setNext(next);
        }
    }
}

接口

interface DoublyLinkable<V, L extends LinkedList.Linkable> extends LinkedList.Linkable<V,L> {
    LinkedList.Linkable getPrev();
    void setPrev(LinkedList.Linkable prev);
}

DoubleNode

public class DoubleNode extends LinkedList.Node implements DoublyLinkable<Integer, LinkedList.Linkable> {
    LinkedList.Linkable prev;

    public DoubleNode(int value) {
        super(value);
    }

    @Override
    public LinkedList.Linkable getPrev() {
        return prev;
    }

    @Override
    public void setPrev(LinkedList.Linkable prev) {
         this.prev = prev;
    }
}

司機

輸出

1, 2, Middle: 3, Prev: 1, Next: 4, 5

public class Driver {

    public static LinkedList getList() {
        LinkedList list = new LinkedList();
        for (int i = 1; i <= 5; i++) {
            list.add(i);
        }
        return list;
    }

    public static void main(String[] args) {

        LinkedList list = getList();

        LinkedList.Linkable head = list.getHead();
        LinkedList.Linkable beforeMiddle = null;
        LinkedList.Linkable middle = list.getHead();
        LinkedList.Linkable end = list.getHead();

        if (head != null) {
            // find the middle of the list
            while (true) {
                if (end.getNext() == null || end.getNext().getNext() == null) break;

                beforeMiddle = middle;
                middle = middle.getNext();

                end = end.getNext().getNext();
            }

            // Replace middle by reassigning the pointer to it
            if (beforeMiddle != null) {

                DoubleNode n = new DoubleNode((int) middle.getValue()); // same value
                n.setPrev(list.getHead()); // point back to the front
                n.setNext(middle.getNext()); // point forward to original value

                beforeMiddle.setNext((DoublyLinkable) n);
                middle = beforeMiddle.getNext();
            }

            // Build the "expected" output
            StringBuilder sb = new StringBuilder();
            final String DELIMITER = ", ";
            head = list.getHead();
            boolean atMiddle = false;
            if (head != null) {
                do {
                    if (head instanceof DoublyLinkable) {
                        atMiddle = true;
                        String out = String.format("Middle: %d, Prev: %d, ", (int) head.getValue(), (int) ((DoublyLinkable) head).getPrev().getValue());
                        sb.append(out);
                    } else {
                        if (atMiddle) {
                            sb.append("Next: ");
                            atMiddle = false;
                        }
                        sb.append(head.getValue()).append(DELIMITER);
                    }

                    head = head.getNext();
                } while (head != null);
            }
            sb.setLength(sb.length() - DELIMITER.length());

            System.out.println(sb.toString());
        }

    }
}

如果沒有,則最好定義一個lenght()函數,這樣在給定一個鏈表的情況下,您可以知道它有多少個節點。

感謝Cereal_Killer對這個答案的先前版本的響應,我注意到列表首先是一個單鏈接列表,您只需要使中間節點既鏈接到下一個節點,又鏈接到某個先前的節點。

現在,我猜您已經定義了兩個結構(Struct,Class或任何其他類型,具體取決於您使用的語言)。 因此,可以說你有Node_s定義為只有一個節點next指針, Node_d同時具有nextprev指針。 Node_d可以從Node_s繼承,因此您只需要在子類中添加prev屬性即可)。 知道了這一點,上面的代碼應該可以滿足您的需求:

函數do_it(my_LinkedListlinkedList){

    int i_middle;
    int length = linkedList.length();

    if ( (length ÷ 2 ) != 0 ) i_middle = length / 2;
    else return -1; 

    Node_s aux = linkedList.first();
    int index = 0;
    Node_d middle= null;

    while (aux != null) {

       if (index == i_middle - 1){ //now aux is the middle's previous node

            middle.data = aux.next.data; //aux.next is the middle singly node, we assignate the data to the new double linked node

            middle.prev = aux; //as we said, aux is the prev to the middle
            midle.next = aux.next.next; //so aux.next.next is the next to the middle
            print(what you need to print);
       }else {
            print("Node " + index " next:  "+ aux.next);
       }//end if

       index++;
       aux = aux.next;
    } //end while

}//end function

前面的代碼應該可以滿足您的需求。 我用某種偽Java代碼編寫了答案,所以如果您不熟悉Java或不了解我的偽代碼做什么,請告訴我。 無論如何,我的代碼的想法可能會遇到麻煩,具體取決於您使用的語言,因此您必須對其進行調整。

請注意,在該程序執行結束時,您的數據結構將不是一個單鏈表,也不是一個雙鏈表,因為您將擁有linkedList.length() - 1節點以一種有符號的方式鏈接,但是中間一個將有兩個鏈接。

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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