List (2): The doubly linked list

First, the doubly linked list

Singly linked list belong to the ring and has a list directional, only one-way traversal, if an incident which has a link breaks, then the list will be behind the data loss can not be recovered. Thus, we can list the different combination of two directions, in addition to the field of data storage, it also has two indicator variables, wherein a pointer to a following node, pointing to the other previous node, this list is called is doubly linked list (Double Linked List).

Since each node has two pointers, can be two-way traffic, it is possible to easily find the front node, from the list while any node can find another node, without passing through other nodes or contrast inversion processing performed faster than fast. Further, if a node is any link broken, it can be traversed in the opposite direction through the list, to quickly reconstruct the complete list.

The biggest advantage of the doubly linked list has two pointers pointing to the front and rear of the two nodes, it is possible to easily find the front node, while any node from a doubly linked list can also find other nodes, without passing through other nodes or contrast inversion processing, execution speed.

The disadvantage is that due to the doubly linked list doubly linked list there are two links, so when a node is added or deleted to spend more time to adjust pointer. Moreover, because each node contains two pointer variables, the more waste space.

Second, the definition of a doubly linked list

Here to introduce two-way linked list data structure. For each node, with three fields, the middle field data, fields left and right sides each have two lists, and the sub-table is LLink RLink, wherein a node point before LLink, RLink point after a node, shown in FIG. :

 

In the doubly linked list, usually plus a list head, the list node does not store any data, the left link field points to the last node in the list, while the right link points to the first node.

If you use the C # language to declare data structures doubly linked list of nodes, then the program code statement is as follows:

namespace DoubleLinkedListDemo 
{ 
    public  class the Node 
    { 
        ///  <Summary> 
        /// data field
         ///  </ Summary> 
        public  int the Data { GET ; SET ;} 

        ///  <Summary> 
        /// subsequent node
         ///  </ Summary> 
        public the node NextNode { GET ; SET ;} 

        ///  <Summary> 
        /// preamble node
         ///  </ Summary> 
        public the node PreNode { GET ; SET ;}

        public Node(int data)
        {
            Data = data;
            NextNode = null;
            PreNode = null;
        }
    }
}

1 insert, a doubly linked list of nodes

 Insert doubly linked list node has the following three cases.

1, before the new node is inserted into the list of the first node

The step of inserting a new node before the first node into the list of:

  1. The right pointer points to the first new node to a node of the original list.
  2. Left pointer to the first node of the original list point to the new node.
  3. Original table pointer points to the linked list the new node, the new node and the left pointer points to null.

as the picture shows:

2, the new node is inserted at the end of this list

The new node is inserted into this end of the link is divided into the following steps:

  1. The original right pointer last node of the list point to the new node.
  2. The left pointer to the new node to the last node in the original list, and the right point to null pointer to the new node.

as the picture shows:

3, the new node is inserted into the intermediate node

After the new node is inserted into the intermediate node (the node pointed PTR), divided into the following steps:

  1. The right pointer ptr node to the new node.
  2. The left pointer ptr points to the new node node.
  3. The left pointer to the next node in the node ptr point to the new node.
  4. The right pointer points to the new node to the next node ptr.

as the picture shows:

2, delete doubly linked list of nodes

Doubly linked list of nodes removed, there are also three cases below.

1, delete the first node in a doubly linked list

The first node in a doubly linked list deletion divided into the following steps:

  1. The list head pointer to point to the original head of the linked list of the second node.
  2. The new list head pointer to null.

as the picture shows:

2, delete the last node in a doubly linked list

删除双向链表的最后一个节点只需要将原链表最后一个节点的前一个节点的右指针指向null即可,如图所示:

3、删除双向链表的中间节点

假设ptr指向的是双向链表的中间节点,删除该节点,分为如下步骤:

  1. 将ptr节点的前一个节点的右指针指向ptr节点的下一个节点。
  2. 将ptr节点的下一个节点的左指针指向ptr节点的前一个节点。

如图所示:

下面我们以具体的代码演示双向链表的数据结构、创立、插入和删除节点,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DoubleLinkedListDemo
{
    /// <summary>
    /// 双向链表类
    /// </summary>
    public class DoubleLinkedList
    {
        /// <summary>
        /// 第一个节点
        /// </summary>
        public Node HeadNode;

        /// <summary>
        /// 尾节点
        /// </summary>
        public Node LastNode;

        /// <summary>
        /// 判断当前双向链表是否为空链表
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty()
        {
            return HeadNode == null;
        }

        /// <summary>
        /// 打印出节点的数据字段
        /// </summary>
        public void Print()
        {
            Node currentNode = HeadNode;
            while(currentNode!=null)
            {
                Console.Write($"{currentNode.Data}  ");
                currentNode = currentNode.NextNode;
            }
            Console.WriteLine();
        }

        /// <summary>
        /// 新增节点,用来创建一个双向链表,每次都是插入到最后一个节点之后
        /// </summary>
        /// <param name="node"></param>
        public void AddNode(Node newNode)
        {
            if(HeadNode==null)
            {
                HeadNode = newNode;
                LastNode = newNode;
                HeadNode.NextNode = LastNode;
                LastNode.PreNode = HeadNode;
                LastNode.NextNode = null;
            }
            else
            {
                LastNode.NextNode = newNode;
                newNode.PreNode = LastNode;
                LastNode = newNode;
                //Node temp = HeadNode;
                //// 循环找到最后一个节点,然后添加
                //// 退出循环时temp就是最后一个节点
                //while(true)
                //{
                //    if(temp.NextNode!=null)
                //    {
                //        // 后移节点
                //        temp = temp.NextNode;
                //    }
                //    else
                //    {
                //        // 退出循环
                //        break;
                //    }
                //}
                //// 将新节点插入到最后一个节点之后
                //temp.NextNode = newNode;
                //newNode.PreNode = temp;
                //
                // LastNode = newNode;
            }
        }

        public void InsertNode(int item,int index)
        {
            Node newNode = new Node(item);
            // 插入头部位置
            if(index==0)
            {
                HeadNode.PreNode = newNode;
                newNode.NextNode = HeadNode;
                HeadNode = newNode;
            }
            else if(index == GetLinkedList()-1)
            {
                // 插入尾部位置
                LastNode.NextNode = newNode;
                newNode.PreNode = LastNode;
                LastNode = newNode;
            }
            else
            {
                // tempNode就是要插入的节点位置
                Node tempNode = HeadNode;
                // 插入中间位置
                for (int i = 0; i < GetLinkedList()-1; i++)
                {
                    if(i!=index)
                    {
                        tempNode = tempNode.NextNode;
                    }
                    else
                    {
                        break;
                    }
                }
                newNode.PreNode = tempNode;
                newNode.NextNode = tempNode.NextNode;
                tempNode.NextNode.PreNode = newNode;
                tempNode.NextNode = newNode;
            }
        }

        /// <summary>
        /// 获取链表长度
        /// </summary>
        /// <returns></returns>
        public int GetLinkedList()
        {
            int length = 0;
            if(HeadNode==null)
            {
                length = 0;
            }
            else
            {
                Node tempNode = HeadNode;
                while(true)
                {
                    if(tempNode.NextNode!=null)
                    {
                        tempNode = tempNode.NextNode;
                        length++;
                    }
                    else
                    {
                        length++;
                        break;
                    }
                }
            }
            return length;
        }


    }
}

Main方法中调用:

using System;

namespace DoubleLinkedListDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Node node1 = new Node(1);
            Node node2 = new Node(34);
            Node node3 = new Node(564);
            Node node4 = new Node(81);
            Node node5 = new Node(6);

            DoubleLinkedList dLinkedList = new DoubleLinkedList();
            dLinkedList.AddNode(node1);
            dLinkedList.AddNode(node2);
            dLinkedList.AddNode(node3);
            dLinkedList.AddNode(node4);
            dLinkedList.AddNode(node5);
            Console.WriteLine("插入前链表");
            dLinkedList.Print();
            // 插入头部
            dLinkedList.InsertNode(29, 0);
            Console.WriteLine("插入头部后链表");
            dLinkedList.Print();
            // 插入尾部
            dLinkedList.InsertNode(724, dLinkedList.GetLinkedList() - 1);
            Console.WriteLine("插入尾部后链表");
            dLinkedList.Print();
            // 插入中间节点
            int index = new Random().Next(1, dLinkedList.GetLinkedList());
            dLinkedList.InsertNode(34242, index);
            Console.WriteLine("插入中间位置后链表");
            dLinkedList.Print();
            Console.ReadKey();
        }
    }
}

程序运行结果:

 

Guess you like

Origin www.cnblogs.com/dotnet261010/p/12316809.html