Data Structure and Algorithm Fundamentals (Wang Zhuo) (5): Complicated operations on (single) linked lists

Table of contents

take the i-th element

Find by value (find its address, and the number of elements in the table (position number))

Insert (insert element e into the i-th position node)

Delete (the ith element node in the linked list)

Establishment of single linked list (head insertion method) <insert in reverse order>

Establishment of single linked list (tail insertion method) <sequential insertion>


Location: PPT Chapter 2: 127


Default prefix:

#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;
};
typedef K Elemtype;         //函数调用状态

struct Lnode
    //node:结; 结点;
{
    Elemtype data;
    Lnode* next;
};
typedef Lnode* LinkList;

take the i-th element

project 1: (I wrote it myself, it can be used if I make do)

Status 取第i个元素(LinkList L, int i,Elemtype e)
{
if (链表是否为空(L))
        cerr << "链表为空" << endl;
if (i < 1)
    cerr << "i不对" << endl;
    LinkList p = L->next;
    int j = 0;
    while (p)
    {
        if (i == j)
        {
            e = p->data;
            break;
        }
        p = p->next;
        j++;
    }
    return true;
}

Project 2: According to what is written in the course (algorithm complexity is lower and easier to use)

Status GetElem“i”(LinkList L, int i, Elemtype e)
{
    LinkList p;
    p = L->next;
    int j = 1;
    while (p && i > j)
    {
        p = p->next;
        j++;
    }
    if (i<0 || i<j || !p)
        return false;
    e=p->data;
    return true;
}

Find by value (find its address, and the number of elements in the table (position number))

project 1:

Status 按值查找地址和位置序号(LinkList L,Elemtype e)
{
    LinkList p; int i=1;
    p = L->next;
    while (p)
    {
        i++;
        if (e == p->data)
        {
            cout << "地址为:  " << p << ";" << endl;
            cout << "位置序号为:  " << i <<";" << endl;
        }
        p = p->next;
    }
    //如果最后运行失败查找不到最后怎么返回ERROR?
    if (p = NULL)
        return NULL;
    return true; 
}

 However, it should be noted that if you want to write this way, you need to add the definition of the manual judgment expression in the declaration of type K:

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

 Project 2: According to what is written in the course (algorithm complexity is lower and easier to use)

Status LocateELem(LinkList 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;
        }
        p = p->next;
    }
    if (p == NULL)
        return NULL;
    return true;
}

In the same way:

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;         //函数调用状态

Insert (insert element e into the i-th position node)

 project 1:

Status 插入(LinkList L,int i,Elemtype e)
{
    LinkList p,s; int j = 1;
    p = L->next;
    s->data = e;
    while (p)//&& j < i)
    { 
        if (j == i-1)
        {
            s->next = p->next;
            p->next = s;
            return true;
        }
        p = p->next;
        j++;
    }
    if (!p || j > i - 1)
        return false;//别忘了写插入非法时的情况
}

 Project 2: According to what is written in the course

Status Listlnsert(LinkList& L, int i, Elemtype e) 
{
    auto p = L; int j = 0;
    while (p && j < i - 1)
    { p = p->next; ++j; } 
    if (!p ||j > i - 1)
        return false;
    auto s = new Lnode; 
    s->data = e; 
    s->next=p->next;
    p->next = s; 
    return true;
}//Listlnsert_L

Question: (Actually, I think it should be the same. I just put this undecided question here for the time being and mark it and hope that it can be answered smoothly in the future.) In this algorithm:

int j = 1;p = L->next;

auto p = L; int j = 0;

Is it equivalent?

Delete (the ith element node in the linked list)

project 1:

Status 删除(LinkList& L, int i)
{
    LinkList p,s,q; int j=1;
    while (p&&j<i-1)
    {
        p->next;
        j++;
    }
    s = p->next;
    q = s->next;
    delete s;
    p = q;
    return true;
}

project 2:

Status 删除(LinkList& L, int i)
{
    LinkList p, s; int j = 1;
    while (p && j < i - 1)
    {
        p->next;
        j++;
    }
    s = (p->next)->next;
    delete p->next;
    p->next = s;
    return true;
}

project 3: According to the video (more rigorous logic)

Status 删除(LinkList& L, int i)
{
    LinkList p = L, s; int j = 1;
    while (p && j < i - 1)
    {
        p = p->next;
        j++;
    }
    if (!p || j > i - 1)
        return false;
    s = p->next;
    p->next = s->next;
    //auto e = s->data;
    delete s;
    return true;
}

The time complexity of each operation:

Singly linked list search, insertion and deletion: O(n)

Insertion and deletion of linear tables: O(1)



Establishment of single linked list (head insertion method) <insert in reverse order>

project 1:

Use the head interpolation method to build a linked list, and insert (input) data nodes (we only enter 3 for simplification here) a, b, c

Status 头插法(LinkList &L)
{
    //创建空链表
    K a, b, c;
    L= new Lnode;//就一个首元结点
   L->next = NULL;
   //L->data里面没什么东西
   //(我们也不知道里面有啥)
  //但可以确定,里面不为空(NULL)

   auto p = new Lnode;//(头)插入
   L->data = c;
   p->next = L->next;
   L->next = p;
   //每次循环的操作,唯一的区别只有:
   //data域输入的数值不同
   auto p = new Lnode;
   L->data = b;
   p->next = L->next;
   L->next = p;
   //
   auto p = new Lnode;
   L->data = a;
   p->next = L->next;
 
}

In fact, this program is wrong, the program design logic:

Points:

about

L= new Lnode;

In fact, I think it is really superfluous:

When the system started with the parameter LinkList &L, didn’t the memory space of L be allocated to you by default in advance? Why are you still working hard here?

In addition, where did the format of L= new Lnode; create space? ? ?

I have learned about the usage of new, only by defining pointers to allocate new space, like:

   Lnode* p = new Lnode;

But since it is available here, we also need to remember:

L= new Lnode;

Right now:

<First address of open space> = new <Data type of open space>

Format (remember to add auto if it has not been defined before)

Finally, after we went in-depth to learn about the usage and format of new, we found that this is not the case:

Not because it means L is a table, but there is a new format as we guessed

It is because the Linklist &L in front of the table header shows that it is originally a pointer and still belongs to the original usage specification

That is to say, if we have defined the variable before (when the formal parameter is passed), then when we open up space later

We don't (and can't) (re)declare the type of the variable

See:

Basics of Data Structure and Algorithm (Wang Zhuo) (8) Attachment: Detailed Explanation of How to Use New_宇-Yu's Blog-CSDN Blog_Data Structure new

C Language Diary 26 Pointers and Functions, Dynamic Storage Allocation - Yu-Yu's Blog - CSDN Blog

end


OK, now, let's fix project 1:

Note that if we want to achieve the "effect we want to achieve" like the previous drawing, it is impossible

We can only do the next best thing:

Let the head pointer point to the head node, and insert a new head node instead of a new head node (impossible)

project 2:

In fact, it is very simple to implement the previous corrections and changes, just:

Change the statement L->data = (node ​​information); to: p->data = (node ​​information);

Status 头插法(LinkList& L)
{
    //创建空链表
    K a, b, c;
    L = new Lnode;//就一个首元结点
    L->next = NULL;//别忘了这句
    //L->data里面没什么东西
    //(我们也不知道里面有啥)
   //但可以确定,里面不为空(NULL)

    auto p = new Lnode;//(头)插入
    p->data = c;
    p->next = L->next;
    L->next = p;
    //
    auto p = new Lnode;
    p->data = b;
    p->next = L->next;
    L->next = p;
    //
    auto p = new Lnode;
    p->data = a;
    p->next = L->next;
}

Formally design and implement the program according to the program flow designed by PPT (148):

Project 3:

Status 头插法()//LinkList &L)
{
    //创建空链表
    auto L = new Lnode;
    //创建新节点
    auto p = new Lnode;
    K an,an_1;
    p->data = an;
    //把新节点和链表串起来
    p->next = L->next;
    L->next = p;
    //重复下一轮循环
    auto p = new Lnode;
    p->next = L->next;
    L->next = p;
}

Realize it as a function that we can implement on the ground: (assuming we input the data of n nodes)

Status 头插法(LinkList& L, int n)
{
    //创建空链表
    auto L = new Lnode;
    L->next = NULL;//别忘了这句
    int i = 1;
    while (i <= n)
    {
        auto p = new Lnode;
        cin >> p->data.a;
        cin >> p->data.b;
        cin >> p->data.c;
        p->next = L->next;
        L->next = p;
        i++;
    }
    return true;
}

This result is basically the same as the standard answer, except that the standard answer uses the for statement:

void CreatListHead(LinkList& L, int n)
{
    auto L = new Lnode;
    L->next = NULL;//别忘了这句
    for (int i = n; i > 0; --i)
        //for (int i = 0; i < n; ++i)
    {
        auto p = new Lnode;
        cin >> p->data.a;
        cin >> p->data.b;
        cin >> p->data.c;
        p->next = L->next;
        L->next = p;
        i++;
    }
}

The return table and constructor table cannot be redefined for final use:

Status 头插法(LinkList& A, int n)
{
    //创建空链表
    auto L = new Lnode;
    L->next = NULL;//别忘了这句
    int i = 1;
    while (i <= n)
    {
        auto p = new Lnode;
        cin >> p->data.a;
        cin >> p->data.b;
        cin >> p->data.c;
        p->next = L->next;
        L->next = p;
        i++;
    }
    A = L;
    return true;
}

Time complexity: O(n) 

Establishment of single linked list (tail insertion method) <sequential insertion>

project 1:

Status 尾插法(int n)
{
    auto L = new Lnode;
    L->next = NULL;
    LinkList r = L;
    for (auto i = 1; i <= n; i++)
    {
        auto p = new Lnode;
        cin >> p->data.a;
        cin >> p->data.b;
        cin >> p->data.c;
        p->next = NULL;
        r->next = p;//尾插
        r = p;
    }
    return true;
}

project 2: (same reason, no more details)

Status 尾插法(LinkList& A, int n)
{
    auto L = new Lnode;
    L->next = NULL;
    LinkList r = L;
    for (auto i = 1; i <= n; i++)
    {
        auto p = new Lnode;
        cin >> p->data.a;
        cin >> p->data.b;
        cin >> p->data.c;
        p->next = NULL;
        r->next = p;//尾插
        r = p;
    }
    A = L;
    return true;
}

Guess you like

Origin blog.csdn.net/Zz_zzzzzzz__/article/details/128166500
Recommended