Data Structure and Algorithm Fundamentals (Wang Zhuo) (6): Merge of circular linked lists with tail pointers (one-way); detailed operations of double linked lists and their insertion and deletion

Table of contents

Merge of circular linked lists with tail pointers (one-way)

doubly linked list

Insertion of doubly linked list

(1): Regarding the word order before and after the four operations (of) of the insertion algorithm

(2): There is a lack of a statement to determine that p points to the successor node

(3): Realize the use of auxiliary functions to return the address of the successor node

(4): Finally

Deletion of doubly linked list

Delete the i-th element of the linked list (the i-th node is known)

Delete the i-th element of the linked list (no node order is given)


Location: PPT Chapter 2: 156


Merge of circular linked lists with tail pointers (one-way)

PPT(157):

Initially set preset conditions before operation​​​​

What we have to do is:

Let the tail node of table A point to the head node of table B, and let the tail node of table B point to the head node of table A:

Project 1:

Status 合并链表(Lnode A,Lnode B)
{
    //前置条件声明:
    LinkList Ta, Tb;//两表的尾指针

    LinkList temp = Ta;//
    Ta->next = Tb->next;//&B;
    Tb->next = temp;
    return true;
}

question:

The temporary variable temp should point to the address pointed to by the end node, not the address of the end node itself;

After the two tables are merged, the head node of the original B table should not exist (in theory, it should be deleted)

in addition:

Ta and Tb are the names of the two tables themselves, but both tables use tail pointers, and there is no point to table B.

Project 2:

Status 合并链表(LinkList Ta, LinkList Tb)
{
    LinkList temp = Ta->next;
    //
    Ta->next = Tb->next->next;//指向b1
    delete Tb->next;
    Tb->next = temp;
    //
    return true;
}

Premise: the two tables are not empty

When we tried to simplify the program and see if we could use temp, we found that: (impossible at all)

When the tail pointer Ta points to the head node of the table Tb, Tb must not be destroyed, and Tb->next cannot be changed

Otherwise, the head node of the table Tb will not be found

Afterwards, if you want to perform the operation of "making the tail pointer Tb point to the head node of the table Ta", you must create (set) another variable to store the address of the head node of Ta, otherwise the basic function of the program will not be realized at all. Function

doubly linked list

In short, the pre-definition of a doubly linked list is as follows:

struct DLnode
{
    Elemtype data;
    DLnode* next,* prior;
};
typedef DLnode* LinkList;

Insertion of doubly linked list

Insert a new element e at the i-th position of the linked list:

Project 1:

Preconditions:

#include<iostream>
using namespace std;
#include<stdlib.h>//存放exit  
#include<math.h>//OVERFLOW,exit

#define MAXlength 100  //初始大小为100,可按需修改

typedef int Status;         //函数调用状态

struct K
{
    float a;
    int b;
    string c;
    bool operator==(K& t)
    {
        return t.a == a && t.b == b;
        //&& t.c = c;
    }
    bool operator!=(K& t)
    {
        return t.a != a || t.b != b;
        //|| t.c = c;
    }
};
typedef K Elemtype;         //函数调用状态

struct DLnode
{
    Elemtype data;
    DLnode* next, * prior;
};
typedef DLnode* DLinkList;

DLinkList p;
//为了后面双链表插入函数里方便使用,我们把p写为全局函数
Status 取第i个元素地址(DLinkList L, int i)//, DLinkList e)
{
    
    p = L->next;
    int j = 1;
    while (p && i > j)
    {
        p = p->next;
        j++;
    }
    if (i < 0 || i < j || !p)
        return false;
    //e = p;
    return true;
}

Algorithm function implementation: 

Status 双链表插入(DLinkList L, int i, Elemtype e)
{
    取第i个元素地址(L, i);
    auto s = new DLnode;
    //auto s = new DLinkList;
    s->data = e;//别忘了写
    s->prior = p->prior;
    s->next = p;
    p->prior->next = s;
    p->prior = s;
    return true;
}

question:

(1): Regarding the word order before and after the four operations (of) of the insertion algorithm

In programming, it is originally intended to retain the next pointer of the predecessor node (inserted node) and the prior pointer of the successor node

So first assign values ​​to the prior and next pointers of the new node

But this will lead to the execution of the statement p->prior->next = s;, because there is an operation to assign a value to the next pointer of the new node

At this time, p->prior has two addresses (both the new node and the predecessor node point to the successor node), which is easy to cause confusion in the program

Therefore, for the program at (this) place, the statement execution restrictions are as follows:

    s->data = e; Don’t forget to write
    s->prior = p->prior; Before execution, the address of p->prior (the predecessor node) must be reserved and cannot be changed (lost)
    p->prior->next = s ;Before execution, it is not appropriate to assign a value to p->prior

As for the statements s->next = p; and p->prior = s;, the addresses s and p themselves will not change in these statements, so don’t worry

Therefore, to sum up, the title requires restrictions on these four sentences:

    s->prior = p->prior; : cannot be preceded by p->prior = s;
    p->prior->next = s; : cannot be preceded by p->prior = s;
    s->next = p; : Any position
    p->prior = s; : not in front of those two sentences

If the above statements are labeled as 1, 2, 3, and 4 respectively, according to the knowledge of permutations and combinations, the programs that can run correctly are nothing more than the following situations:

1234

2134

3124

3214

1324

2314

 However, even at this point in the research, there are still problems with the program

In fact, the address of the i-th element is not passed into the program, and the modification is as follows:

(2): There is a lack of a statement to determine that p points to the successor node

Project 2:(1234)

DLinkList p,a;//改动1
Status 取第i个元素地址(DLinkList L, int i, DLinkList a)//改动2
{

    p = L->next;
    int j = 1;
    while (p && i > j)
    {
        p = p->next;
        j++;
    }
    if (i < 0 || i < j || !p)
        return false;
    a = p;//改动3
    return true;
}


Status 双链表插入(DLinkList L, int i, Elemtype e)
{
    取第i个元素地址(L, i, a);
    if (a != p)//改动5
        return false;

    auto s = new DLnode;

    s->data = e;//别忘了写

    s->prior = p->prior;
    p->prior->next = s;
    s->next = p;// 
    p->prior = s;
    return true;
}

Make sure that p points to the real statement of the successor node: change 5

(3): Realize the use of auxiliary functions to return the address of the successor node

In addition, if you want to fully guarantee the encapsulation of the function when you write the function "take the i-th element address" before, you can also change the function to:

DLinkList 取第i个元素地址(DLinkList L, int i, DLinkList a)
{
    DLinkList p;
    p = L->next;
    int j = 1;
    while (p && i > j)
    {
        p = p->next;
        j++;
    }
    if (i < 0 || i < j || !p) 
        return 0;
    a = p;
}

At this time, the reference function statement in the inserted function is:

Status 双链表插入(DLinkList L, int i, Elemtype e)
{
    DLinkList p,a;
    取第i个元素地址(L, i, a);
    if ( a!= p)
        return false;

    auto s = new DLnode;
...

Or written more simply and concisely:

DLinkList 取第i个元素地址(DLinkList L, int i)
{
    DLinkList p;
    p = L->next;
    int j = 1;
    while (p && i > j)
    {
        p = p->next;
        j++;
    }
    if (i < 0 || i < j || !p)
        return 0;
    return p;
}

At this time, the reference function statement in the inserted function is:

Status 双链表插入(DLinkList L, int i, Elemtype e)
{
    DLinkList p;
    if ( 取第i个元素地址(L, i)!= p)
        return false;

    auto s = new DLnode;

    s->data = e;//别忘了写

    s->prior = p->prior;
    p->prior->next = s;
    s->next = p;
    p->prior = s;
    return true;
}

(4): Finally

Regarding the newly created node s, we can do the same as the program in the previous example:

Create a new node s directly, and the node name is directly used as a pointer to the node (this is more convenient and faster)

It can also be said in class:

Create a new node and create a pointer to point to the node: (this is the most common usage we introduced when we were learning C++)

    DLnode *s = new DLnode;

Deletion of doubly linked list

Delete the i-th element of the linked list (the i-th node is known)

Status 双链表删除(DLinkList L, int i, Elemtype e)
{
    DLinkList p = 取第i个元素地址(L, i);
    if (p->data != e)
        return false;

    p->next->prior = p->prior;
    //后继节点的前驱设置为前驱结点地址
    p->prior->next = p->next;
    delete p;
    return true;
}

 The preconditions are the same as (3) the second program version

Here, the program we designed believes that: e is used to represent the node information itself (known node information)

What PPT wants to express is: e is used to return node information:

Status 双链表删除(DLinkList L, int i, Elemtype &e)
{
    DLinkList p;
    if (p != 取第i个元素地址(L, i))
        return false;

    e = p->data;

    p->next->prior = p->prior;
    //后继节点的前驱设置为前驱结点地址
    p->prior->next = p->next;
    delete p;
    return true;
}

 Time complexity: O(1)

Delete the i-th element of the linked list (no node order is given)

Since you didn't give us the node order, then you need to give us at least the node information data

Otherwise, if you don’t give anything, we will definitely not be able to find where this node is.

DLinkList LocateELem(DLinkList L, Elemtype e)
{
    //在线性表L中查找值为e的数据元素
    //找到,则返回L中值为e的数据元素的地址,查找失败返回NULL
    auto p = L->next; int i = 1;
    while (p && p->data != e)
    {
        i++;
        if (e == p->data)
        {
            //cout << "地址为:  " << p << ";" << endl;
            //cout << "位置序号为:  " << i << ";" << endl;
            return p;
        }
        p = p->next;
    }
    if (p == NULL)
        return NULL;
    //return 1;
}
Status 双链表删除(DLinkList L, Elemtype &e)
{
    DLinkList p;
    if (p != LocateELem(L, e))
        return false;

    e = p->data;

    p->next->prior = p->prior;
    //后继节点的前驱设置为前驱结点地址
    p->prior->next = p->next;
    delete p;
    return true;
}

 Time complexity: O(n)

Because the time complexity required by the search algorithm itself is O(n)

Guess you like

Origin blog.csdn.net/Zz_zzzzzzz__/article/details/128260357