[Data Structure C++] Linear Table (2) Chained Storage

Linked storage is somewhat different from sequential storage, and it is more difficult than sequential storage.

Before understanding linked storage, let's review pointers.

1. Pointer

1. What is a pointer

Pointer: A variable used to store an address whose value points to the address of another variable.
So I think it can be regarded as an ordinary variable, but the ordinary variable stores data such as: int i=5, and the pointer stores an address, and this address can point to a variable.

2. Pointer variables

1), define the pointer variable: int *p;

Note : p here is a variable, just like i in int i, and int * means that p is a pointer variable of type int, just like i is a variable of type int.
Note : The pointer variable must be initialized, such as int *p=NULL. Otherwise, p is a wild pointer and an error will be reported.

2), *p in the program (except definition)

The address of a variable pointed to by p, then * p is the variable pointed to by the stored address
. The example is as follows:

#include <iostream>

using namespace std;

int main()
{
    
    
    int a=5;
    int *p=&a;
    cout<<"&a="<<&a<<endl;
    cout<<"p="<<p<<endl;
    cout<<"a="<<a<<endl;
    cout<<"*p="<<*p<<endl;
    return 0;
}

output:
insert image description here

3. Pointers and arrays

1), pointer and array name

Let's look at the following code first:

#include <iostream>

using namespace std;

int main()
{
    
    
    int *p;
    int a[5]={
    
    0,1,2,3,4};
    p=a;
    for(int i=0;i<5;i++)
    {
    
    
        cout<<p[i]<<" ";
    }
    cout<<endl;
    return 0;
}

The output result is:
insert image description here
It can be seen that p can be used to represent a, why is this?
Because a is both the array name and the first address pointing to the entire element, so use p to point to a, that is, you can use p to access the array a;
but I want to say: the p pointer is a pointer variable, and the array name a is just a pointer constant.

2), pointer array

The essence of the pointer array is an array, and each member in the array is a pointer,
such as int *Array[5];
that means:
insert image description here

Two, linked list

1. Linked list definition

The difference between chained storage and sequential storage is that sequential storage uses continuous addresses, but chained storage uses a group of arbitrary storage units to store data, and the addresses can be continuous or discontinuous.
In order to represent (storage) the logical relationship (linear) between elements, while storing each element, it also stores the information of related elements (storage address of related elements), that is, pointers are used to represent the logical relationship between elements. The space occupied by storing a data element is:
insert image description here

2. Head node

Sometimes for the convenience of operation, a "head node" is added before the first node of the linked list. This node does not store elements, and its pointer points to the first element of the linear list.
After having the head node, the operation of inserting a node before the first element node and deleting the first node is unified with the operation of other nodes. (not required)

3. Linked list implementation

We use two classes to realize the definition and operation of the linked list, one is the linked list node class LinkNode, which is used to define some pointer nodes and initialize and allocate memory; the other is the linked list class, which is used to define some operations on the linked list. (The linked list class is a friend of the linked list node class)

1), define the node class

typedef int T;
class Linklist;
class LinkNode
{
    
    
   friend class LinkList;//声名友元
private:
   LinkNode *link;
   T data;
public:
   LinkNode(LinkNode *ptr=NULL)
   {
    
    
     link=ptr;
   }
   LinkNode(const T &item,LinkNode *ptr=NULL)//item是默认参数
   {
    
    
      data=item;
      link=ptr;
   }
   ~LinkNode(){
    
    };
};

Note: The default parameter must be the rightmost parameter in the function parameter list, which can be omitted when the function is called. If the number of actual parameters is inconsistent with the number of formal parameters when calling the function, the default is from left to right Matches right, so default arguments are placed at the far right of the function list. When calling, if the investment does not write parameters, it will be the first one; if a T-type data is written, it will be the second one

2), define the linked list class

class LinkList
{
    
    
private:
    LinkNode *first;
public:
    LinkList();//构造函数
    ~LinkList();
    int Length();//返回链表的长度
    bool Insert(int i,T x);//向链表中插入元素
    LinkNode *Locate(int i);//返回链表i处的节点值
    void Input(T endTag);//按条件输入(顺序)
    void Input2(T endTag);//按条件输入(逆序)
    void PrintList();//打印链表
    bool Delete(T &x);//删除值为x的节点
    void Search(T &x);//按值查找
    bool Find(T x);//查询链表中是否存在x
    void Cross(LinkList &A,LinkList &B,LinkList &C);//链表的交操作
    void Union(LinkList &A,LinkList &B);//链表的并操作
    void Sort();//对链表进行排序
};

3), constructor

LinkList::LinkList()
{
    
    
    first = new LinkNode;//定义一个头结点并进行初始化
    first->data = 0;
    first->link = NULL;
}

4), destructor

LinkList::~LinkList()
{
    
    
    delete first;//删除头结点
}

5) Return the length of the linked list

Since first is the head node we defined, we should set p as the next node of first, and calculate the length from here.

int LinkList::Length()
{
    
    
    int i=0;
    LinkNode *p=first->link;
    while(p!=NULL)
    {
    
    
        i++;
        p=p->link;
    }
    return i;
}

6) Return the node value at i in the linked list

LinkNode *LinkList::Locate(int i)
{
    
    
    LinkNode *p=first;
    int j=0;
    if(i<0)
    {
    
    
        return NULL;
    }
    while(p!=NULL&&j<i)
    {
    
    
        p=p->link;
        j++;
    }
    return p;
}

7) Insert elements into the linked list

Put p in the previous position of the node to be inserted , define a new node s with data value x, point the next node of s to the next node of p, and then set the next node of p point to s

bool LinkList::Insert(int i,T x)
{
    
    
    LinkNode *p=Locate(i-1);
    if(p==NULL)
    {
    
    
        return false;
    }
    LinkNode *s=new LinkNode(x);
    s->link=p->link;
    p->link=s;
}

insert image description here
Some operations are analyzed below:
s->link=p->link: change the next node pointed by s to the next node pointed by p
insert image description here
p->link=s: point the next node of p to the s
insert image description here

8), input by condition (sequence)

New elements are always chained after, elements are entered in natural order

void LinkList::Input(T endTag)
{
    
    
    LinkNode *newNode,*r;
    T val;
    cin>>val;
    r=first;
    while(val!=endTag)
    {
    
    
        newNode=new LinkNode(val);//申请空间,存储读入的元素
        r->link=newNode;
        r=newNode;
        cin>>val;
    }
    r->link=NULL;
}

insert image description here
insert image description here

9), input by condition (reverse order)

New elements are always linked in front, entered in reverse order
this is very similar to insert

void LinkList::Input2(T endTag)
{
    
    
    LinkNode *newNode,*r;
    T val;
    cin>>val;
    r=first;
    while(val!=endTag)
    {
    
    
        newNode=new LinkNode(val);
        newNode->link=r->link;
        r->link=newNode;
        cin>>val;
    }
}

10), print linked list

void LinkList::PrintList()
{
    
    
    LinkNode *p=first->link;
    while(p!=NULL)
    {
    
    
        cout<<p->data<<" ";
        p=p->link;
    }
    cout<<endl;
}

11) Delete the node whose value is x

The basic idea of ​​the algorithm: find the i-1th element and make the i+1th element its successor. Frees the i-th element.

bool LinkList::Delete(T &x)
{
    
    
    LinkNode * p, *q = NULL;
    p = first->link;
    if (p == NULL)
    {
    
    
        return false;
    }
    while (p->data!=x&&p->link!=NULL)
    {
    
    
        q = p;//找到第i-1个元素,并赋给q
        p = p->link;//让p到第i个元素
    }
    if (p->data == x)
    {
    
    
        q->link = p->link;//让q的下一个元素直接指向p的下一个元素
        delete p;
    }
}

insert image description here

12) Find by value

void LinkList::Search(T &x)
{
    
    
    LinkNode *p=first->link;
    int count=1,flag=0;
    while(p!=NULL)
    {
    
    
        if(p->data==x)
        {
    
    
            flag=1;
            break;
        }
        count++;
        p=p->link;
    }
    if(flag)
    {
    
    
        cout<<x<<" is located at index of "<<count<<endl;
    }
    else
    {
    
    
        cout<<x<<" is not found"<<endl;
    }
}

13) Query whether x exists in the linked list

bool LinkList::Find(T x)
{
    
    
    LinkNode *p=first;
    while(p!=NULL)
    {
    
    
        if(p->data==x)
        {
    
    
            return true;
        }
        p=p->link;
    }
    return false;
}

14) Intersection operation of linked list

Traverse in linked list B, take out the value and look for it in linked list A, if found, add it to linked list C

void LinkList::Cross(LinkList &A,LinkList &B,LinkList &C)
{
    
    
    T t;
    for(int i=1; i<=B.Length(); i++)
    {
    
    
        t=B.Locate(i)->data;
        if(A.Find(t))
        {
    
    
            C.Insert(C.Length()+1,t);
        }
    }
}

15), and operation of linked list

Traverse in linked list B, take out the value and look for it in linked list A, if not found, add it at the end of linked list A

void LinkList::Union(LinkList &A,LinkList &B)
{
    
    
    T t;
    for(int i=1; i<=B.Length(); i++)
    {
    
    
        t=B.Locate(i)->data;
        if(!A.Find(t))
        {
    
    
            A.Insert(A.Length()+1,t);
        }
    }
}

16) Sort the linked list

similar to bubble sort

void LinkList::Sort()
{
    
    
    LinkNode *p=first,*q=NULL;
    while(p!=q)
    {
    
    
        while(p->link!=q)
        {
    
    
            if(p->data>p->link->data)
            {
    
    
                int t=p->data;
                p->data=p->link->data;
                p->link->data=t;
            }
            //如果没有找到满足if条件的,就一直往后遍历
            //如果找到了,进行交换后再往后遍历
            //一直到p->link!=q
            p=p->link;
        }
        //将q指向p,在将p置为first头结点,从头再进行遍历操作
        q=p;
        p=first;
    }
}

4. The complete program

#include <iostream>
#include <stdio.h>

using namespace std;

typedef int T;

class LinkList;
class LinkNode
{
    
    
    friend class LinkList;
private:
    LinkNode *link;
    T data;
public:
    LinkNode(LinkNode *ptr=NULL)
    {
    
    
        link=ptr;
    }
    LinkNode(const T &item,LinkNode *ptr=NULL)
    {
    
    
        data=item;
        link=ptr;
    }
    ~LinkNode() {
    
    };
};

class LinkList
{
    
    
private:
    LinkNode *first;
public:
    LinkList();//构造函数
    ~LinkList();
    int Length();//返回链表的长度
    bool Insert(int i,T x);//向链表中插入元素
    LinkNode *Locate(int i);//返回链表i出的节点值
    void Input(T endTag);//按条件输入(顺序)
    void Input2(T endTag);//按条件输入(逆序)
    void PrintList();//打印链表
    bool Delete(T &x);//删除值为x的节点
    void Search(T &x);//按值查找
    bool Find(T x);//查询链表中是否存在x
    void Cross(LinkList &A,LinkList &B,LinkList &C);//链表的交操作
    void Union(LinkList &A,LinkList &B);//链表的并操作
    void Sort();//对链表进行排序
};

LinkList::LinkList()
{
    
    
    first = new LinkNode;
    first->data = 0;
    first->link = NULL;
}


LinkNode *LinkList::Locate(int i)
{
    
    
    LinkNode *p=first;
    int j=0;
    if(i<0)
    {
    
    
        return NULL;
    }
    while(p!=NULL&&j<i)
    {
    
    
        p=p->link;
        j++;
    }
    return p;
}

LinkList::~LinkList()
{
    
    
    delete first;
}

bool LinkList::Insert(int i,T x)
{
    
    
    LinkNode *p=Locate(i-1);
    if(p==NULL)
    {
    
    
        return false;
    }
    LinkNode *newNode=new LinkNode(x);
    newNode->link=p->link;
    p->link=newNode;
}

void LinkList::Input(T endTag)
{
    
    
    LinkNode *newNode,*r;
    T val;
    cin>>val;
    r=first;
    while(val!=endTag)
    {
    
    
        newNode=new LinkNode(val);
        r->link=newNode;
        r=newNode;
        cin>>val;
    }
    r->link=NULL;
}

void LinkList::Input2(T endTag)
{
    
    
    LinkNode *newNode,*r;
    T val;
    cin>>val;
    r=first;
    while(val!=endTag)
    {
    
    
        newNode=new LinkNode(val);
        newNode->link=r->link;
        r->link=newNode;
        cin>>val;
    }
}

void LinkList::PrintList()
{
    
    
    LinkNode *p=first->link;
    while(p!=NULL)
    {
    
    
        cout<<p->data<<" ";
        p=p->link;
    }
    cout<<endl;
}

bool LinkList::Delete(T &x)
{
    
    
    LinkNode * p, *q = NULL;
    p = first->link;
    if (p == NULL)
    {
    
    
        return false;
    }
    while (p->data!=x&&p->link!=NULL)
    {
    
    
        q = p;
        p = p->link;
    }
    if (p->data == x)
    {
    
    
        q->link = p->link;
        delete p;
    }

}

int LinkList::Length()
{
    
    
    int i=0;
    LinkNode *p=first->link;
    while(p!=NULL)
    {
    
    
        i++;
        p=p->link;
    }
    return i;
}

void LinkList::Search(T &x)
{
    
    
    LinkNode *p=first->link;
    int count=1,flag=0;
    while(p!=NULL)
    {
    
    
        if(p->data==x)
        {
    
    
            flag=1;
            break;
        }
        count++;
        p=p->link;
    }
    if(flag)
    {
    
    
        cout<<x<<" is located at index of "<<count<<endl;
    }
    else
    {
    
    
        cout<<x<<" is not found"<<endl;
    }
}

bool LinkList::Find(T x)
{
    
    
    LinkNode *p=first;
    while(p!=NULL)
    {
    
    
        if(p->data==x)
        {
    
    
            return true;
        }
        p=p->link;
    }
    return false;
}

void LinkList::Cross(LinkList &A,LinkList &B,LinkList &C)
{
    
    
    T t;
    for(int i=1; i<=B.Length(); i++)
    {
    
    
        t=B.Locate(i)->data;
        if(A.Find(t))
        {
    
    
            C.Insert(C.Length()+1,t);
        }
    }
}

void LinkList::Union(LinkList &A,LinkList &B)
{
    
    
    T t;
    for(int i=1; i<=B.Length(); i++)
    {
    
    
        t=B.Locate(i)->data;
        if(!A.Find(t))
        {
    
    
            A.Insert(A.Length()+1,t);
        }
    }
}

void LinkList::Sort()
{
    
    
    LinkNode *p=first,*q=NULL;
    while(p!=q)
    {
    
    
        while(p->link!=q)
        {
    
    
            if(p->data>p->link->data)
            {
    
    
                int t=p->data;
                p->data=p->link->data;
                p->link->data=t;
            }
            p=p->link;
        }
        q=p;
        p=first;
    }
}

int main()
{
    
    
    int n,m,t=0,a[10000],x1,y1,x2,x3,x4;
    cin>>n;
    LinkList p,q,r;
    p.Input(n);
    cout<<"A is created as: ";
    p.PrintList();
    cin>>x1>>y1;
    p.Insert(x1,y1);
    cout<<"After inserted A is ";
    p.PrintList();
    cin>>x2;
    p.Delete(x2);
    cout<<"After deleted A is ";
    p.PrintList();
    cin>>x3;
    p.Search(x3);
    cin>>x4;
    p.Search(x4);
    cin>>m;
    q.Input(m);
    cout<<"B is created as: ";
    q.PrintList();
    p.Cross(p,q,r);
    cout<<"A cross B is ";
    r.PrintList();
    p.Union(p,q);
    cout<<"A union B is ";
    p.PrintList();
    p.Sort();
    cout<<"A union B in sequence is ";
    p.PrintList();
    return 0;
}

5. Description

1) Every time a node pointer is defined with a node class, it must be initialized

2) The linked list should try to define a head node for easy operation, but the head node does not belong to the whole linked list.

insert image description here

3), About the defined node initialization allocation memory

If we want to insert a certain number, first use the constructor of the node class to initialize
LinkNode *newNode=new LinkNode(val), so that we can apply for space and allocate memory for the number.

Guess you like

Origin blog.csdn.net/qq_45397526/article/details/105161519
Recommended