[PHP data structure] other forms of linked list

Time:2021-10-19

In the last article, we have said that the linked list has several other forms besides the simple one-way linked list. Of course, this is also a major feature of the linked list structure, which is very flexible and convenient. Let’s simply think about it. If the next of the last node refers back to the first node, then a ring will be formed, which is a circular linked list. If we add a prev attribute pointing to the previous node on each node, the linked list will become a two-way linked list. If we make the next of the last node point to the first node and the prev of the first node point to the last node on the basis of the two-way linked list, it is a two-way circular linked list. Let’s take a specific look.

Circular linked list

As mentioned above, let the last node point to the first node, and the resulting linked list is a circular linked list, as shown in the following figure:

https://imgs.developpaper.com/imgs/1575433-20210721085957770-791991466.jpg

We will not explain the operation of circular linked list in detail. In fact, most of the codes are the same as one-way linked list, but we need to pay attention to two places:

1. During initialization and insertion operations, pay attention to the pointing of the last node, and the next of the last node should point to the first node

2. The condition for judging whether the linked list traversal is completed is item – > next = = head, that is, judge whether the next node of this node is the head node, and the linked list traversal is completed.

Bidirectional linked list

The bidirectional linked list adds an attribute to the LinkedList class to point to the previous node.

//Bidirectional linked list
class LinkedList
{
    public $data;

    public $prev;
    public $next;
}

https://imgs.developpaper.com/imgs/1575433-20210721085957989-1193664931.jpg

Next, we initialize a two-way linked list.

/**
 *Generate linked list
 */
function createLinkedList()
{
    $list = new LinkedList();
    $list->data = null;
    $list->next = null;
    $list->prev = null; // **  All are initialized to null**
    return $list;
}

/**
 *Initialize linked list
 *@ param array $data is the data to be saved in the linked list. Here, take the array as the reference
 *@ return LinkedList linked list data
 */
function Init(array $data)
{
    //Initialization
    $list = createLinkedList();
    $r = $list;
    foreach ($data as $key => $value) {
        $link = new LinkedList();
        $link->data = $value;
        $link->next = null;
        $r->next = $link;
        $link->prev = $r; // **  Add superior direction**
        $r = $link;
    }
    return $list;
}

$link = Init(range(1, 10));

var_dump($link);
var_dump($link->next->next->next->next);
// object(LinkedList)#5 (3) {
//     ["data"]=>
//     int(4)
//     ["prev"]=>
//     object(LinkedList)#4 (3) {
//       ["data"]=>
//       int(3)
//       ["prev"]=>
//       object(LinkedList)#3 (3) {
//         ["data"]=>
//         int(2)
//         ["prev"]=>
//         object(LinkedList)#2 (3) {
//           ["data"]=>
//           int(1)
//           ["prev"]=>
//           object(LinkedList)#1 (3) {
//             ["data"]=>
//             NULL
//             ["prev"]=>
//             NULL
//             ["next"]=>
//             *RECURSION*
//           }
//           ["next"]=>
//           *RECURSION*
//         }
//         ["next"]=>
//         *RECURSION*
//       }
//       ["next"]=>
//       *RECURSION*
//     }
//     ["next"]=>
//     object(LinkedList)#6 (3) {
//       ["data"]=>
//       int(5)
//       ["prev"]=>
//       *RECURSION*
//       ["next"]=>
//       object(LinkedList)#7 (3) {
//         ["data"]=>
//         int(6)
//         ["prev"]=>
//         *RECURSION*
//         ["next"]=>
//         object(LinkedList)#8 (3) {
//           ["data"]=>
//           int(7)
//           ["prev"]=>
//           *RECURSION*
//           ["next"]=>
//           object(LinkedList)#9 (3) {
//             ["data"]=>
//             int(8)
//             ["prev"]=>
//             *RECURSION*
//             ["next"]=>
//             object(LinkedList)#10 (3) {
//               ["data"]=>
//               int(9)
//               ["prev"]=>
//               *RECURSION*
//               ["next"]=>
//               object(LinkedList)#11 (3) {
//                 ["data"]=>
//                 int(10)
//                 ["prev"]=>
//                 *RECURSION*
//                 ["next"]=>
//                 NULL
//               }
//             }
//           }
//         }
//       }
//     }
//   }

echo $link->next->next->next->next->data, PHP_EOL; // 4
echo $link->next->next->next->next->prev->data, PHP_EOL; // 3

It can be seen that the difference from the one-way linked list is that more operations on the prev attribute are added. It’s easy to understand here. Printing the linked list directly will display a lot of * recurrence * content, which is an output protection mechanism of PHP. This identification indicates that the current attribute variable has recursive type.

/**
 *Insert an element at the specified position in the linked list
 *@ param LinkedList $list linked list data
 *@ param int $I location
 *@ param mixed $data data
 */
function Insert(LinkedList &$list, int $i, $data)
{
    $j = 0;
    $item = $list;
    //Traverse the linked list to find the previous position of the specified position
    while ($j < $i - 1) {
        $item = $item->next;
        $j++;
    }

    //If item does not exist or $I > N + 1 or $I < 0
    if ($item == null || $j > $i - 1) {
        return false;
    }

    //Create a new node
    $s = new LinkedList();
    $s->data = $data;

    //The next node of the newly created node points to the next hop node of the original I-1 node, that is, the current i-node
    $s->next = $item->next;

    //* * add the parent point of the newly created node**
    $s->prev = $item;

    //Point the next hop node of I-1 node to s, insert s into the specified I position, and make the original I position element into I + 1 position
    $item->next = $s;

    //* * point the prev of the child node to the newly created node**
    $s->next->prev = $s;

    return true;
}

The insertion of the linked list actually adds two lines of code. One is the direction of the parent of the current newly created node, that is, specify the parent of the new node as I-1 nodes. The other is to modify the parent point of the original I location node to the newly created node.

/**
 *Delete the element at the specified position in the linked list
 *@ param LinkedList $list linked list data
 *@ param int $I location
 */
function Delete(LinkedList &$list, int $i)
{
    $j = 0;
    $item = $list;
    //Traverse the linked list to find the previous position of the specified position
    while ($j < $i - 1) {
        $item = $item->next;
        $j++;
    }
    //If item does not exist or $I > N + 1 or $I < 0
    if ($item == null || $j > $i - 1) {
        return false;
    }

    //Use a temporary node to save the current node information, $item is the I-1 node, so $item - > next is the current I node we want to find
    $temp = $item->next;
    //Let the current node, that is, the previous node of the target node, change the next hop of the node at I-1 (the node at the original I position) into the next hop of the node at the original I position, and let the node at I position leave the chain
    $item->next = $temp->next;

    //* * make the parent pointer of the next target node point to the current node**
    $temp->next->prev = $item;

    return true;
}

Similar to the insert node operation, the delete node operation not only changes the point of the next node of the data of the I-1 location node to the point of the next level node of the I node, but also changes the point of the parent node of the next level node of I to the I-1 node.

In fact, the definition and operation of a two-way linked list are not much different from that of a one-way linked list, that is, there is an additional prev to point to the upper level node. In essence, there are only more operations on the attribute prev. So, what benefits can this extra superior pointer bring? When traversing the linked list, we use prev to traverse the linked list in a reverse way. When searching for an element, we can search from two directions at the same time. Does the efficiency double all at once. The original time complexity of O (n) can instantly become the time complexity of O (n / 2).

Bidirectional circular linked list

Finally, we also briefly introduce the bidirectional circular linked list. As the name suggests, it is to add the concept of circular linked list on the basis of two-way linked list. Let the next of the last node point to the head node and the prev of the head node point to the last node. It’s easy to say, but it’s actually much more complicated to implement, because you should not only pay attention to the pointing of the lower level node of the last node, but also pay attention to the pointing of the upper level node of the head node. So we won’t do more code demonstration here. The most important thing is to pay more attention to the direction of their parent and child nodes when inserting and deleting header and tail nodes.

https://imgs.developpaper.com/imgs/1575433-20210721085958320-75877218.jpg

summary

Suddenly found a new world? There are so many forms of linked lists. Of course, we haven’t finished yet. We still have a very tall cross linked list, but in fact, the cross linked list only adds more pointing attributes. The basic data field is always the same data. In fact, the most common one-way linked list, that is, the one introduced in detail in the last article, is the key point we really need to master in learning linked list. Therefore, you don’t have to worry or panic. If you master the ordinary one-way linked list, you can kill most people. What about today’s learning? If you can master the best, you can’t master it. At least be familiar with your face. The most important thing in life is to be happy. Don’t force yourself too hard. If you are too hard, either Jackie Chan or adults. It’s most important to recognize your current situation and ability.

That’s all about linear tables. This is the storage problem of physical structure. Next, we will the world of logical structure. It also starts from the simplest, that is, stacks and queues. Don’t be afraid. Compared with trees and pictures, they really sprinkle water!!

Test code:

https://github.com/zhangyue0503/Data-structure-and-algorithm/blob/master/2. Other forms of linear list / source / 2.4% 20 linked list.php

reference material:

Data structure, Second Edition, Yan Weimin

Data structure, Second Edition, Chen Yue

High score notes on data structure, 2020 edition, tianqin postgraduate entrance examination

Official account: hard core project manager

Add wechat / QQ friends: [xiaoyuezigonggong / 149844827] get free PHP and project management learning materials

Tiktok, official account, voice, headline search, hard core project manager.

Station B ID: 482780532