简体   繁体   English

双链表实现

[英]Doubly Linked Lists Implementation

I have looked at most threads here about Doubly linked lists but still unclear about the following. 我在这里查看了有关双链表的大多数主题,但仍不清楚以下内容。

I am practicing the Goodrich and Tamassia book in Java. 我正在用Java练习Goodrich和Tamassia的书。 About doubly linked lists, please correct me if I am wrong, it is different from a singly linked list in that a node could be inserted anywhere, not just after the head or after the tail using both the next and prev nodes available, while in singly linked lists, this insertion anywhere in the list is not possible? 关于双向链表,如果我错了,请纠正我,它与单链表的不同之处在于,可以在下一个节点和上一个节点同时将节点插入到任何位置,而不仅仅是在头尾之后。单链列表,无法在列表的任何位置插入?

If one wants to insert a node in a doubly linked list, then the default argument should be either the node after the to-be inserted node or node before the to-be inserted node ? 如果要在双向链表中插入节点,则默认参数应该是要插入的节点之后的节点还是要插入的节点之前的节点? But if this is so, then I don't understand how to pass the node before or after. 但是,如果是这样,那么我不了解如何在此之前或之后传递节点。 Should we be displaying all nodes that were inserted till now and ask the user to select the node before or after which some new node is to be inserted ? 我们是否应该显示到目前为止已插入的所有节点,并要求用户选择要在其中插入一些新节点的节点? My doubt is how to pass this default node. 我的疑问是如何传递此默认节点。 Because I assume that will require the next and prev nodes of these nodes as well. 因为我假设这也将需要这些节点的下一个和上一个节点。

For eg, Head<->A<->B<->C<->D<->E<->tail 例如, Head<->A<->B<->C<->D<->E<->tail

If Z is the new node to be inserted after say D, then how should node D be passed? 如果Z是在说D之后要插入的新节点,那么应该如何传递节点D? I am confused with this though it seems pretty simple to most. 我对此感到困惑,尽管对于大多数人来说这似乎很简单。

But pl do explain. 但是请解释一下。

Thanks, Sanjay 谢谢,桑杰

Assuming a Node class like this: 假设这样的Node类:

public class Node {
    public Node next = null;
    public Node previous = null;
    public Object value;
}

Then you can define: 然后可以定义:

public void insertBefore(Node node, Node insert)
{
    Node previousNode = node.previous;

    insert.next = node;
    insert.previous = previousNode;

    if(previousNode != null)
        previousNode.next = insert;

    node.previous = insert;
}

and

public void insertAfter(Node node, Node insert)
{
    Node nextNode = node.next;

    insert.previous = node;
    insert.next = nextNode;

    if(nextNode!= null)
        nextNode.previous = insert;

    node.next = insert;
}

Hope that helps 希望能有所帮助

it is different from a singly linked list in that a node could be inserted anywhere, not just after the head or after the tail using both the next and prev nodes available, while in singly linked lists, this insertion anywhere in the list is not possible? 它与单链接列表的不同之处在于,可以使用下一个和上一个节点将节点插入到任何位置,而不是仅在头尾之后,而在单链接列表中,无法在列表中的任何位置插入节点?

This is wrong. 错了 You can insert nodes in the middle of a singly linked list just fine. 您可以在单链列表的中间插入节点。 The only difference is that a doubly linked list is easier to navigate, since you can walk it forward and backward from any given node. 唯一的区别是,双向链接列表更易于浏览,因为您可以从任何给定节点向前和向后浏览它。

If one wants to insert a node in a doubly linked list, then the default argument should be either the node after the to-be inserted node or node before the to-be inserted node? 如果要在双向链表中插入节点,那么默认参数应该是要插入节点之后的节点还是要插入节点之前的节点?

That depends entirely on what you are using the list for. 这完全取决于您使用列表的目的。 Linked lists are not really a good general-purpose data structure due to their poor random access performance. 由于链接列表的随机访问性能较差,因此它并不是真正的通用数据结构。 Because of that, they are usually only used for algorithms that iterate over the list anyway and insert or remove nodes while they do it. 因此,它们通常仅用于无论如何都要遍历列表并在执行操作时插入或删除节点的算法。

But if this is so, then I don't understand how to pass the node before or after. 但是,如果是这样,那么我不了解如何在此之前或之后传递节点。 Should we be displaying all nodes that were inserted till now and ask the user to select the node before or after which some new node is to be inserted? 我们是否应该显示到目前为止已插入的所有节点,并要求用户选择要在其上插入一些新节点的节点?

You're approaching this from the wrong way, trying to write an application around a certain data structure. 您正以错误的方式来处理此问题,试图围绕某个数据结构编写应用程序。 Normally you start out with the application's end-user requirements and then decide which data structure is best used to satisfy those requirements. 通常,您从应用程序的最终用户需求开始,然后确定最适合用来满足那些需求的数据结构。 A User should never have to understand low-level internals of a program like linked lists. 用户永远不必了解链接列表之类的程序的低级内部。

  1. You can insert in a single linked list too. 您也可以在单个链接列表中插入。 A->B Becomes A->C->B, all you have to do is change A's next node reference and set C's to B. A-> B变为A-> C-> B,您要做的就是更改A的下一个节点引用并将C设置为B。
  2. It makes more sense to insert after the selected node by default. 默认情况下,将其插入所选节点之后更为合理。
  3. You set D's next node to Z, E's previous node to Z, Z's next node to E and Z's previous node to D. 您将D的下一个节点设置为Z,E的上一个节点设置为Z,Z的下一个节点设置为E,Z的上一个节点设置为D。

I hope I understood your questions correctly, they're a bit confusing. 希望我能正确理解您的问题,这有点令人困惑。

Doubly Linked List Implementation using JAVA. 使用JAVA的双链表实现。 Implemented Operations are : 已实施的操作有:

  1. Insert node in DLL. 在DLL中插入节点。
  2. Remove nth position element from DLL. 从DLL中删除第n个position元素。
  3. Find position of element in DLL. 查找元素在DLL中的位置。
  4. Retrieve all nodes from DLL. 从DLL中检索所有节点。
  5. Retrieve all nodes in reverse from DLL. 从DLL反向检索所有节点。
  6. Get length of DLL. 获取DLL的长度。

     package com.config; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class DLL { public static void main(String args[]) throws NumberFormatException, IOException{ int choice = 0; Node temp = null; Node head = null; boolean flage = true; int nodeCounter = 0; BufferedReader read = new BufferedReader(new InputStreamReader(System.in)); do{ Node node = new Node(); System.out.println("Enter Node data"); node.data = Integer.parseInt(read.readLine()); if(flage){ flage = false; head = node; } if(temp!=null){ temp.next = node; node.prev = temp; } temp = node; nodeCounter++; System.out.println("Press 0 to quite for more node entry."); choice = Integer.parseInt(read.readLine()); }while(choice != 0); temp.next = head; head.prev = temp; System.out.println("You have created "+nodeCounter+" nodes in doubly linked list"); System.out.println("Retriving and Manipulation Operation perform : "); Node node = head; do{ System.out.println("Press 1 for get all nodes from doubly linked list."); System.out.println("Press 2 for get all nodes in reverse from doubly linked list."); System.out.println("Press 3 for get length of doubly linked list."); System.out.println("Press 4 for remove nth node from doubly linked list."); System.out.println("Press 5 for find node in doubly linked list."); System.out.println("Press 0 for quite."); choice = Integer.parseInt(read.readLine()); switch (choice) { case 1: Node.getAllNodes(node); break; case 2: Node.getAllNodesReverse(node); break; case 3 : System.out.println("Length : "+Node.getDoublyLinkedListLength(node)); break; case 4 : System.out.println("Enter Position to remove from DLL"); choice = Integer.parseInt(read.readLine()); node = Node.removeNthNode(node, choice); break; case 5 :System.out.println("Enter Node data to find in DLL"); choice = Integer.parseInt(read.readLine()); choice = Node.findNode(node, choice); if(choice == 0){ System.out.println("Node Not Found in DLL"); choice = 1; }else System.out.println("Node Position : "+choice); break; default: break; } }while(choice != 0); } } class Node{ int data = 0; Node next = null; Node prev = null; public static void getAllNodes(Node head){ int nodeCounter = 0; if(head!=null){ Node tail = head.prev; while(head.next != tail.next ){ nodeCounter++; System.out.println(nodeCounter+". Node : "+head.data); head = head.next; } nodeCounter++; System.out.println(nodeCounter+". Node : "+head.data); } } public static int getDoublyLinkedListLength(Node head){ int nodeCounter = 0; if(head!=null){ Node tail = head.prev; while(head.next != tail.next ){ nodeCounter++; head = head.next; } nodeCounter++; } return nodeCounter; } public static int findNode(Node head,int data){ int nodeCounter = 0; boolean flage = false; if(head!=null){ Node tail = head.prev; while(head.next != tail.next ){ nodeCounter++; if(head.data == data){ flage = true; break; } head = head.next; } } return flage ? nodeCounter : 0; } public static void getAllNodesReverse(Node head){ if(head!= null){ int nodeCounter = 0; Node tail = head.prev; while(tail.prev!= head.prev){ nodeCounter++; System.out.println(nodeCounter+". Node : "+tail.data); tail = tail.prev; } nodeCounter++; System.out.println(nodeCounter+". Node : "+tail.data); } } public static Node removeNthNode(Node head, int removePosition){ int length = getDoublyLinkedListLength(head); if(head!=null){ int counter = 1; if(length >2){ if(length+1 > removePosition && removePosition > 0){ while(counter != removePosition){ counter++; head = head.next; } head.prev.next = head.next; head.next.prev = head.prev; }else{ System.out.println("Given Position not exist"); } }else{ System.out.println("At least two nodes must be in doubly linked list."); } } if(removePosition==1 || removePosition==length) return head.next; else return head; } } 

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

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