DS005 Data Structure-Research on the Principles of Single Linked List Implementation-An example for teacher Yan Weimin's textbook

1. The sequence table is so good, why do you need a linked list?

Disadvantages of sequence table:

•In addition to the end of the list, inserting and deleting elements in the sequence table requires moving other elements, which is inefficient; the average time complexity is O(n).

• The sequence table needs continuous space. When the amount of data is relatively large, if there is not enough continuous space, the sequence table will fail! !

 

To solve this shortcoming, a linked list is designed. The insertion and deletion of the linked list do not need to move other elements, and the efficiency of insertion and deletion is high; but the advantage of random access is lost.

 

Another: This is a disruptive innovation, starting anew, not repairing within the framework of sequential storage! !

Singly linked list is the simplest chain structure. From this divergence and extension, more complex structures, such as trees and graphs, can be constructed.

The foundation is not strong, the ground is shaking, and the linked list must be learned well.

Second, the definition of singly linked list

• A singly linked list connects sequence data like a "chain" by storing the addresses of subsequent nodes in the current node, so it is called a linked list.

• The "single" of the singly linked list means that only one address data is stored in the current node, that is, the address of the subsequent data node.

Three, the node form of the singly linked list

Fourth, the overall form of the singly linked list

 

 

Setting up the head node in the singly linked list is to facilitate the insertion and deletion of nodes at the head of the linked list.

      The head node and data node of the singly linked list we talked about in this section are the same type.

       Sometimes for convenience, a pointer to the head of the linked list, a pointer to the end of the linked list and an integer representing the length of the linked list can be set in the head node. At this time, the type of the head node is different from the type of the linked list node.

The header files and symbol constants used in the following programs are as follows:

#include<iostream>
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status; 
//Status is the function return value type, and its value is the function result status code.
typedef int ElemType; 
//ElemType is a definable data type, this is set to int type

 

Five, the C++ description of the linked list node

typedef struct LNode {     ElemType data; //The data field of the node     struct LNode *next; //The pointer field of the node } LNode, *LinkList; //LinkList is the pointer type to the structure LNode


In this way, head is the head pointer, and length records the number of element nodes in the linked list, excluding the head node.

Six, generate a node    

LNode *CreateNode(ElemType e)
{//为元素e生成一个结点
	LNode *t=new LNode;
	if(t==0) return 0;
	t->data=e;
	t->next=0;
	return t; 
}

Use the new operator to apply for node type space from the operating system.

If the operating system says that I am not rich, and refuses it, it returns 0, which is a null pointer, otherwise it returns the address of the new node. 

Seven, initialization

At the beginning, a head node is generated and implemented in the constructor.

Status InitList(LinkList &L) 
{ //算法2.6 单链表的初始化
	//构造一个空的单链表L
	L = CreateNode(0);
	if(L==0) return ERROR;
	return OK;
}

head is a variable, which stores the address, which is the address of the head node, which has no name. 

 

8. Insert an element after a certain node

void insert(LNode* p, LNode* q)
{//p是链表中某个结点的指针,q是一个新结点的指针
	//将q插入到p的后面
	q->next = p->next;
	p->next = q;
}

void insert(LNode* p, ElemType x)
{//在指针p所指的结点后面插入x
	LNode* q, * t;

	t = CreateNode(x);
	insert(p, t);		

}

C++ function overloading has the same function name but different parameters. 

Insert the q node after the node p. You must not disconnect the pointer after p first. Before disconnecting, there must be a pointer to the node after the original p.

Otherwise, the node will be lost.

Nine, insert elements after the head node

void push_head(LinkList &L, ElemType e)
{//在头结点后面插入数据
	insert(L,e) ;	
}

With the foreshadowing of the previous insert function, the operation of inserting a node at the head is so simple.

10. Insert a node at the end of the linked list

 

void push_back(LinkList &L, ElemType e)
{//在头结点后面插入数据
	LNode *p=L;
	while(p->next) 
	{
		p=p->next; 
	} 
	insert(p,e) ;	
}

 First find the end node of the linked list, point to it with pointer p, and then insert data after p.

11. Get the address of the i-th node

LNode *Locate_i(LinkList &L,int i)
{//查找 第i个结点,用指针指向它,并返回该指针
	if(i<0) return 0;//不合法 
	if(i==0)return L;//把头结点看做0号结点 
	LNode *p=L->next;
	int j=1;
	while(j<i && p)
	{
		p=p->next;
		j++; 
	}
	return p;
}

Finding the i-th node in the singly linked list is a basic operation. 

12. Insert data before the i-th node

Status ListInsert(LinkList &L, int i, ElemType e) 
{ //算法2.9 单链表的插入
	//在带头结点的单链表L中第i个位置插入值为e的新结点
	LNode *p=Locate_i(L,i-1);//寻找第i-1个位置 
	if(p==0) return ERROR;//找不到插入位置 
	LNode *t=CreateNode(e);//为e生成结点 
	t->next=p->next;
	p->next=t; 
	return OK;
} 

To insert data at the i-th node, insert data after the i-1th node, and you need to find the i-1th node first.

13. Delete the i-th node

Status ListDelete(LinkList &L, int i) 
{ //算法2.9 单链表的删除
	//在带头结点的单链表L中,删除第i个位置	
	LinkList p, q;
	p=Locate_i(L,i-1);//找到第i-1个结点
	if(p==0) return ERROR; 
	q = p->next; //临时保存被删结点的地址以备释放 
	if(q==0) return ERROR;
	p->next = q->next; //改变删除结点前驱结点的指针域 
	delete q; //释放删除结点的空间 
	
	return OK;
}

To delete the i-th node, you need to find the i-1th node first. 

14. Search in the linked list

 


LNode *LocateElem(LinkList L, int e) 
{ //算法2.8 按值查找
	//在带头结点的单链表L中查找值为e的元素
	LinkList p = L->next;
	//顺链域向后扫描,直到p为空或p所指结点的数据域等于e
	while (p)
	{
		if(p->data==e)
			return p;//查找成功 
		p=p->next;
	}	
	return 0; //查找失败 
}

15. Release the space occupied by the singly linked list

Implemented in the destructor

void freeAll(LinkList &L)
{//释放所有结点空间
	LNode* p;	
	while (L->next)
	{
		p = L->next;
		L->next = p->next;
		delete p;
	}
	delete L;
	L = 0;	
}

16. Complete code

 

#include<iostream>
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status; 
//Status 是函数返回值类型,其值是函数结果状态代码。
typedef int ElemType; 
//ElemType 为可定义的数据类型,此设为int类型

typedef struct LNode {
	ElemType data; //结点的数据域
	struct LNode *next; //结点的指针域
} LNode, *LinkList; //LinkList为指向结构体LNode的指针类型


LNode *CreateNode(ElemType e)
{//为元素e生成一个结点
	LNode *t=new LNode;
	if(t==0) return 0;
	t->data=e;
	t->next=0;
	return t; 
}

Status InitList(LinkList &L) 
{ //算法2.6 单链表的初始化
	//构造一个空的单链表L
	L = CreateNode(0);
	if(L==0) return ERROR;
	return OK;
}

void insert(LNode* p, LNode* q)
{//p是链表中某个结点的指针,q是一个新结点的指针
	//将q插入到p的后面
	q->next = p->next;
	p->next = q;
}

void insert(LNode* p, ElemType x)
{//在指针p所指的结点后面插入x
	LNode* q, * t;

	t = CreateNode(x);
	insert(p, t);		

}

void push_head(LinkList &L, ElemType e)
{//在头结点后面插入数据
	insert(L,e) ;	
}

void push_back(LinkList &L, ElemType e)
{//在头结点后面插入数据
	LNode *p=L;
	while(p->next) 
	{
		p=p->next; 
	} 
	insert(p,e) ;	
}

LNode *Locate_i(LinkList &L,int i)
{//查找 第i个结点,用指针指向它,并返回该指针
	if(i<0) return 0;//不合法 
	if(i==0)return L;//把头结点看做0号结点 
	LNode *p=L->next;
	int j=1;
	while(j<i && p)
	{
		p=p->next;
		j++; 
	}
	return p;
}


Status ListInsert(LinkList &L, int i, ElemType e) 
{ //算法2.9 单链表的插入
	//在带头结点的单链表L中第i个位置插入值为e的新结点
	LNode *p=Locate_i(L,i-1);//寻找第i-1个位置 
	if(p==0) return ERROR;//找不到插入位置 
	LNode *t=CreateNode(e);//为e生成结点 
	t->next=p->next;
	p->next=t; 
	return OK;
} 


Status GetElem(LinkList L, int i, ElemType &e)
 { //算法2.7 单链表的取值
	//在带头结点的单链表L中查找第i个元素
	//用e返回L中第i个数据元素的值
	LNode *p=Locate_i(L,i);
	if(p==0) return ERROR;//i不合法 
	e = p->data; //取第i个结点的数据域
	return OK;
} 


LNode *LocateElem(LinkList L, int e) 
{ //算法2.8 按值查找
	//在带头结点的单链表L中查找值为e的元素
	LinkList p = L->next;
	//顺链域向后扫描,直到p为空或p所指结点的数据域等于e
	while (p)
	{
		if(p->data==e)
			return p;//查找成功 
		p=p->next;
	}	
	return 0; //查找失败 
}

Status ListDelete(LinkList &L, int i) 
{ //算法2.9 单链表的删除
	//在带头结点的单链表L中,删除第i个位置	
	LinkList p, q;
	p=Locate_i(L,i-1);//找到第i-1个结点
	if(p==0) return ERROR; 
	q = p->next; //临时保存被删结点的地址以备释放 
	if(q==0) return ERROR;
	p->next = q->next; //改变删除结点前驱结点的指针域 
	delete q; //释放删除结点的空间 
	
	return OK;
}

void freeAll(LinkList &L)
{//释放所有结点空间
	LNode* p;	
	while (L->next)
	{
		p = L->next;
		L->next = p->next;
		delete p;
	}
	delete L;
	L = 0;	
}

void print(LinkList &L)
{
	if(L==0)
		cout<<"链表没有头结点"<<endl;
	LNode *p=L->next;
	while(p)
	{
		cout<<p->data<<" ";
		p=p->next;
	}
	cout<<"\n";
}

int main()
{
	LNode *H;
	InitList(H);
	push_head(H,1);
	print(H);
	push_head(H,3);
	print(H);
	push_head(H,5);
	print(H);
	
	push_back(H,6);push_back(H,7);push_back(H,8);
	print(H);
	 
	
	int x;
	GetElem(H,2,x);
	cout<<x<<endl;
	
	LNode *p=LocateElem(H,3);
	cout<<p->data<<endl;
	
	print(H);
	
	ListDelete(H,3);
	print(H);
	
		
	ListInsert(H,1,1);
	print(H);
	ListInsert(H,2,2);
	print(H);
	ListInsert(H,3,3);
	print(H);
	ListInsert(H,4,4);
	print(H);
	freeAll(H);
	print(H);
	
	
	return 0;
}

17. Running results

 

Guess you like

Origin blog.csdn.net/weixin_43917370/article/details/108688559