简体   繁体   English

在单链接列表中添加双链接列表节点

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

Given singly Linked List: 1 -> 2 -> 3 -> 4 -> 5 -> null 给定单链表: 1 -> 2 -> 3 -> 4 -> 5 -> null
Modify middle element as doubly Linked List Node 修改中间元素为双链表节点
here middle element is 3 这里中间元素是3
3 -> next should point to 4 3 -> next应指向4
3 -> prev should point to 1 3 -> prev应该指向1

Can any one suggest how can it be done ? 有人可以建议怎么做吗? interviewer gave me hint use interface . 面试官给我提示use interface but I couldn't figure it out how. 但我不知道怎么做。
I have to iterate over this linked list and print all the node and when it reaches to the middle, print where next and prev is pointing to, then print till the end of the list. 我必须遍历此链接列表并打印所有节点,当它到达中间时,打印next和prev指向的位置,然后打印到列表末尾。
Expected output : 1, 2, Middle: 3, Prev: 1, Next: 4, 5 Expected output1, 2, Middle: 3, Prev: 1, Next: 4, 5

I'm facing problem in adding the middle node. 我在添加中间节点时遇到问题。

By definition , a single-linked list consists of single-linked nodes only, and a double-linked consists of double-linked nodes only. 根据定义 ,单链列表仅包含单链节点,而双链列表仅包含双链节点。 Otherwise. 除此以外。 it is neither. 两者都不是。

By definition the field prev of a double-linked list must point to the previous element. 根据定义 ,双向链接列表的字段prev 必须指向上一个元素。

Whatever you are supposed to build. 无论您打算建造什么。 It's something not well specified. 没有明确说明。 So if you really were asked this in an interview (and did not misunderstand the question - maybe he wanted you to point out that ghis violates the interface?) this is a case for the code horror stories of http://thedailywtf.com/ - section "incompetent interviewers". 因此,如果您在采访中真的被问到了这一点(并且没有误解这个问题-也许他想让您指出ghis 违反了界面?)这是http://thedailywtf.com/的代码恐怖故事的一种情况-“无能的面试官”。

So, this " works ", but if this is expected to be answered on an interview, it is way too much work. 因此,这是“ 有效的 ”,但是如果希望在采访中得到回答,那就太麻烦了。

LinkedList 链表

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 接口

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

DoubleNode 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;
    }
}

Driver 司机

Outputs 输出

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());
        }

    }
}

If you haven't, you'd better define a lenght() function so given one linked list you can know how many nodes does it have. 如果没有,则最好定义一个lenght()函数,这样在给定一个链表的情况下,您可以知道它有多少个节点。

Thanks to the response of Cereal_Killer to the previous version of this answer, I noticed that the list is firstly a singly linked list, and you just have to make the middle node be linked both to the next node and to some previous node. 感谢Cereal_Killer对这个答案的先前版本的响应,我注意到列表首先是一个单链接列表,您只需要使中间节点既链接到下一个节点,又链接到某个先前的节点。

Now I guess that you have defined two structures (Struct, Class or whatever depending on the language you're using). 现在,我猜您已经定义了两个结构(Struct,Class或任何其他类型,具体取决于您使用的语言)。 So lets say you have Node_s defined as a node with only a next pointer, and Node_d with both a next and a prev pointer. 因此,可以说你有Node_s定义为只有一个节点next指针, Node_d同时具有nextprev指针。 ( Node_d may inherite from Node_s so you just have to add the prev attribute in the child class). Node_d可以从Node_s继承,因此您只需要在子类中添加prev属性即可)。 Knowing this, the code above should be doing what you need: 知道了这一点,上面的代码应该可以满足您的需求:

function do_it(my_LinkedList linkedList){ 函数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

This previous code should be doing what you need. 前面的代码应该可以满足您的需求。 I wrote the answer in some kind of pseudo-java code so if you're not familiar with Java or don't understand what my pseudo-code does, please let me know. 我用某种伪Java代码编写了答案,所以如果您不熟悉Java或不了解我的伪代码做什么,请告诉我。 Anyway, the idea of my code may present some troubles depending on the language you're working with, so you'll have to adapt it. 无论如何,我的代码的想法可能会遇到麻烦,具体取决于您使用的语言,因此您必须对其进行调整。

Note that at the end of the execution of this program, your data structure won't be a singly linked list, and neither a double one, since you'll have linkedList.length() - 1 nodes linked in a signly way but the middle one will have two links. 请注意,在该程序执行结束时,您的数据结构将不是一个单链表,也不是一个双链表,因为您将拥有linkedList.length() - 1节点以一种有符号的方式链接,但是中间一个将有两个链接。

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM