[Postgraduate entrance examination data structure] Chapter 2 Basic knowledge and operations of singly linked lists

Article directory

 Basic knowledge of singly linked lists

definition

Head pointer and head node

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

Node type definition

Initialize singly linked list

Create singly linked list

Head insertion method - reverse table creation

Tail insertion method - forward table construction

insert element

Insert in bit order (lead node)

Insert in bit order (without leading node)

Insert forward according to specified node

Insert after specified node

Delete element

Delete in bit order (leading node)

Delete in bit order (without leading node)

Deletion of specified node

Find element

Bitwise search

Find by value

 Find the length of the table

Summarize

Head pointer and head 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.

Guess you like

Origin blog.csdn.net/qq_52487066/article/details/129604063