Linked storage is somewhat different from sequential storage, and it is more difficult than sequential storage.
Before understanding linked storage, let's review pointers.
chain storage
- 1. Pointer
- Two, linked list
-
- 1. Linked list definition
- 2. Head node
- 3. Linked list implementation
-
- 1), define the node class
- 2), define the linked list class
- 3), constructor
- 4), destructor
- 5) Return the length of the linked list
- 6) Return the node value at i in the linked list
- 7) Insert elements into the linked list
- 8), input by condition (sequence)
- 9), input by condition (reverse order)
- 10), print linked list
- 11) Delete the node whose value is x
- 12) Find by value
- 13) Query whether x exists in the linked list
- 14) Intersection operation of linked list
- 15), and operation of linked list
- 16) Sort the linked list
- 4. The complete program
- 5. Description
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:
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:
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:
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:
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;
}
Some operations are analyzed below:
s->link=p->link: change the next node pointed by s to the next node pointed by p
p->link=s: point the next node of p to the s
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;
}
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;
}
}
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.
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.