Article directory
Basic knowledge of singly linked lists
The difference between head pointer and head node
Differences in conditions for judging empty tables
Advantages of introducing head nodes
Basic operations of singly linked list
Head insertion method - reverse table creation
Tail insertion method - forward table construction
Insert in bit order (lead node)
Insert in bit order (without leading node)
Insert forward according to specified node
Delete in bit order (leading node)
Delete in bit order (without leading node)
Headed nodes and non-headed nodes
Head insertion and tail insertion
The code order of modifying the pointer field and data field cannot be reversed.
Basic knowledge of singly linked lists
definition
Linked storage of linear tables is also called singly linked lists , which refers to storing data elements in linear tables through a set of arbitrary storage units. In order to establish a linear relationship between data elements, for each linked list node, in addition to storing the element's own information, it also needs to store a pointer to its successor . The structure of a singly linked list is shown in the figure below:
- The variable that stores data is called the data field , usually recorded as data
- The pointer that stores the position of the subsequent node is called the pointer field , usually recorded as next
The node types of a singly linked list are described as follows:
//定义单链表的结点类型
typedef struct LNode{
ElemType data;//数据域
struct LNode *next;//指针域
}LNode,*LinkList;
Head pointer and head node
Usually a head pointer is used to uniquely identify a singly linked list, such as singly linked list L. When the head pointer is NULL, it represents an empty list . In addition, for the convenience of operation, a node is usually appended before the first node of the singly linked list, called the head node . The data field of the head node may not store any data, or may store some additional information such as table length, etc. The pointer field of the head node points to the first element node of the linear list , as shown in the following figure:
The difference between head pointer and head node
- The head pointer always points to the first node of the linked list
- The head node is the first node of the linked list with the head node
Differences in conditions for judging empty tables
- The condition for the leading node to determine an empty table is: L->next=NULL
- The condition for judging an empty table without a head node and only a head pointer is: L==NULL
Advantages of introducing head nodes
- Since the position of the first data node is stored in the pointer field of the head node, the operation at the first position of the linked list is consistent with the operation at other positions in the list , and no additional special processing is required; On the contrary, if there is no head node and only a head pointer, special processing is required for the operation at a position.
- Regardless of whether the linked list is empty or not, its head pointer is a non-null pointer pointing to the head node (the pointer field of the head node in an empty list is empty), so empty lists and non-empty lists are also unified .
Basic operations of singly linked list
Node type definition
//定义单链表的结点类型
typedef struct LNode{
int data;//数据域
struct LNode *next;//指针域
}LNode,*LinkList;
Initialize singly linked list
Single linked list with head node
//初始化单链表(带头结点)
bool InitList(LinkList &L){
L=(LNode*)malloc(sizeof(LNode));//分配一个头结点的内存空间
if(L==NULL)return false;//内存不足,分配失败
L->next=NULL;//链表中暂时没有元素
return true;
}
Single linked list without head node
//初始化单链表(不带头结点)
bool InitList(LinkList &L){
L=NULL;//链表中暂时没有元素
return true;
}
Create singly linked list
Head insertion method - reverse table creation
Use the " head insertion method " to create a table, and the order of reading data is opposite to the order of elements in the linked list.
//头插法建表:读入数据的顺序与链表中元素的顺序相反
LinkList List_HeadInsert(LinkList &L){
LNode *s;
int x;
//L=(LinkList)malloc(sizeof(LNode));//创建头结点
//L->next=NULL;//初始化为空链表
scanf("%d",&x);
while(x!=-1){
s=(LNode*)malloc(sizeof(LNode));//开辟一个新的内存空间存放新的结点
s->data=x;
s->next=L->next;//设置新结点的指针域等于原头结点指向的第一个结点
L->next=s;//头指针重新指向链表的第一个结点
scanf("%d",&x);
}
return L;
}
Tail insertion method - forward table construction
Use the " tail insertion method " to create a table, and the order of reading data is the same as the order of elements in the linked list.
//尾插法建表:读入数据的顺序与链表中元素的顺序一致
LinkList List_TailInsert(LinkList &L){
int x;//存放用户输入的数字
L=(LinkList)malloc(sizeof(LNode));//建立头结点,初始化空表
LNode *s,*r=L;//r为表尾指针
scanf("%d",&x);
while(x!=-1){
s=(LNode*)malloc(sizeof(LNode));//在内存中开辟出一个新结点的空间
s->data=x;
r->next=s;
r=s;//r指向新的表尾结点
scanf("%d",&x);
}
r->next=NULL;//尾指针的指针域置空
return L;
}
insert element
Insert in bit order (lead node)
//按照位序插入:在表L中的第i个位置插入指定元素e
bool InsertList1(LinkList &L,int i,int e){
if(i<1)return false;
LNode *p;//游标指针
int j=0;//表示p指向的是第几个结点
p=L;//L指向头结点
while(p!=NULL&&j<i-1){
p=p->next;
j++;
}
if(p==NULL)return false;//i值不合法
LNode *s=(LNode*)malloc(sizeof(LNode));//开辟一个新的内存空间给新结点存储待插入值
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
Insert in bit order (without leading node)
There is no leading node, that is, there is no " 0th " node, so when it is to be inserted at the first position, that is, i=1, special processing must be performed, which is different from the operation of the leading node. Pay attention to the comparison.
//按照位序插入(不带头结点):在表L中的第i个位置插入指定元素e
bool InsertList2(LinkList &L,int i,int e){
if(i<1)return false;
//插入到第一个位置时与插入到其它结点的操作不相同
if(i==1){
LNode *s=(LNode*)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s;
return true;
}
LNode *p;//游标指针
int j=1;//表示p指向的是第几个结点
p=L;//L指向头结点
while(p!=NULL&&j<i-1){
p=p->next;
j++;
}
if(p==NULL)return false;//i值不合法
LNode *s=(LNode*)malloc(sizeof(LNode));//开辟一个新的内存空间给新结点存储待插入值
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
Insert forward according to specified node
//指定结点的前插操作
bool InsertPriorNode(LNode *p,int e){
if(p==NULL)return false;
LNode *s=(LNode*)malloc(sizeof(LNode));
if(s==NULL)return false;//内存不够,分配空间失败
s->next=p->next;
p->next=s;
//交换p、s中的值达到变相的前插操作,即把新结点s放到了p的前面
int temp=p->data;
p->data=s->data;
s->data=temp;
p->data=e;
return true;
}
Insert after specified node
//指定结点的后插
bool ListInsert(LinkList &L,int i,int e){
if(i<1)return false;
LNode *p;//指针p指向当前扫描到的结点
int j=0;//当前p指向的是第几个结点
p=L;
//先找到第i-1个结点
while(p!=null&&j<i-1){
p=p->next;
j++;
}
if(p==NULL){
return false;
}
LNode *s=(LNode*)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
Delete element
Delete in bit order (leading node)
//按位序删除(带头结点)
bool ListDelete(LinkList &L,int i,int &e){
if(i<1)return false;
LNode *p;//指针p指向当前扫描到的结点
int j=0;
p=L;
while(p!=NULL&&j<i-1){
p=p->next;
j++;
}
if(p==NULL)return false;
if(p->next==NULL)return false;//第i-1个结点之后已经没有其它结点了
LNode *q=p->next;//令q指向被删除的结点
e=q->data;//用e返回被删除的元素值
p->next=q->next;//断链
free(q);//释放被删除结点原来占用的内存空间
return true;
}
Delete in bit order (without leading node)
Without a head node, special processing is required when deleting the first element, i.e. i=1.
if(i==1){
LNode *q=L;
e=q->data;
L=q->next;
free(q);
return true;
}
Deletion of specified node
//指定结点的删除
bool DeleteNode(LNode *p){
if(p==NULL)
return false;
LNode *q=p->next;
p->data=p->next->data;//和后继结点交换数据域
p->next=q->next;//将*q结点从链中"断开"
free(q);
return true;
}
Find element
Bitwise search
//按位查找(带头结点)
LNode * GetItem(LinkList L,int i){
if(i<0)
return NULL;
LNode *p;//游标指针
int j=0;//p指向的是第几个结点
p=L;
//循环找到第i个结点
while(p!=NULL&&j<i){
p=p->next;
j++;
}
return p;
}
Find by value
//按值查找
LNode * LocateItem(LinkList L,int e){
LNode *p=L->next;
//从第一个结点开始寻找数据域为e的结点
while(p!=NULL&&p->data!=e){
p=p->next;
}
return p;//找到后返回该点的指针,否则返回NULL
}
Find the length of the table
The table length refers to the number of element nodes, excluding the head node.
//求表的长度
int GetLength(LinkList L){
int len=0;
LNode *p=L;
while(p->next!=NULL){
p=p->next;
len++;
}
return len;
}
Summarize
Head pointer and head node
- Usually the head pointer is used to identify a singly linked list, such as singly linked list L. When the head pointer is NULL, it is an empty list.
- The node appended in front of the first element node of the singly linked list is called the head node , which is set for the convenience of subsequent operations. The pointer field of the head node points to the first element node of the singly linked list.
Headed nodes and non-headed nodes
- In the question, be sure to check whether it is the leading node. When processing the first element
- The processing operations of leading nodes and non-leading nodes are different.
Head insertion and tail insertion
- The head insertion method is used to build a table . The order of reading data is opposite to the order of elements in the linked list . The reverse of the linked list is to use the head insertion method to operate.
- The tail insertion method is used to build a table . The order of reading data is the same as the order of elements in the linked list . This method is generally used to build a table.
The code order of modifying the pointer field and data field cannot be reversed.
As shown in the figure above, the code at the green arrow and the code at the yellow arrow cannot be reversed . Imagine that if the order is reversed, p->next=s is executed first; that is, the next node pointed by p is s, and then s- is executed. >next=p->next; At this time, it becomes the pointer field of s to store s. This causes the pointer field of s to point to itself, which is obviously wrong. In some subsequent codes, readers can experience by themselves the different operation results caused by the different code sequences. This detail must be paid attention to!
END.