[original] on the writing method of pointer linked list

Posted by ik on Sun, 06 Mar 2022 04:22:06 +0100

preface

Recently, I came to update this series. In fact, I feel that the pointer is still very important for us. The pointer is a "nightmare" for beginners. Its difficulty stems from its flexibility.
In this article, I want to write about the practical application of the pointer. If the pointer is only some test questions, it will be meaningless. Most importantly, pointers are an indispensable part of C language and even C + +.

Simple review of linked list

Linked list is a data structure.

For a linked list, each node has two fields, namely data field and pointer field. The data field is used to store the number of the linked list, and the pointer field is used to store the address of the next node. In particular, the pointer field of the last node is set to NULL.
In this way, there is no need to store the whole linked list in order.

For data insertion and deletion, the linked list only needs to create a new node:

The time complexity of insertion and deletion is O(1), and there is no need to move elements. For ordinary linear tables, data needs to be moved, so the time complexity is O(n).

Structure declaration

For the structure of the linked list, we can write as follows:

typedef struct List{
	int data;
	List *next;
	List(int x){
		this->data=x;
		next=NULL;
	}
};
List *lst;

Data is the data field and next is the pointer field.

Among them, List(x) is a constructor, which makes it easy to write when using new for node allocation. When allocating, it needs to be written as follows:

l=new List(x);

This constructor does two things: one is to assign data and the other is to set next to NULL.

Supplement 1: this pointer
Where, write this - > data. This refers to the structure itself, for example, call:

l=new List(x);

this points to l. this is a special pointer. There is a figurative way:

When you enter a house, you can see tables, chairs, floors, etc., but you can't see the whole picture of the house.
For an instance of a class, you can see its member functions and member variables, but what about the instance itself?
this is a pointer that points to your instance itself all the time.

Of course, it's OK not to write this here. It's just a matter of writing.

Supplementary 2: - > operator
This operator is called "arrow".
Suppose we have the following structure:

struct info{
  string name;
  int age;
}

If you now have a common variable x, then quote the age in it and write: x.age
If you now have a pointer variable p, reference the age in it and write p - > age
That is, for a pointer structure, you need to use the - > operator to refer to its members.
In essence, P - > age is equivalent to (* P) Age, note that although the brackets here are troublesome, they cannot be omitted. The arrow operator is just a simple way to write.

Add elements at the end of the linked list

We know that if the current node of a linked list is NULL, it must be the last node. Therefore, we can write recursively. If the current node of the linked list is not NULL, the next node will be.

void add(List *&l,int x){
	if(l==NULL){
		l=new List(x);
		return;
	}
	else add(l->next,x);
}

l=new List(x);, The constructor method mentioned before.
Add (L - > next, x) means to find the next node.

Supplement 3: * & what the hell is it!

As we know, & is a reference passing parameter. I've written about the pointer (3) before, Web link
If I'm too lazy to find the original text, I'll post the original text directly here:

Here, * denotes pointer and & denotes reference passing, so the combination is the reference passing of pointer. Although the declaration seems annoying, it is just like that when you understand it.

Output all elements of the linked list

I directly posted the function without difficulty. The logic is similar to the add function.

void write(List *l){
	if(l==NULL)return;
	else{
		printf("%d ",l->data);
		write(l->next);
	}
}

Insert element

The flexibility of linked list is its insertion and deletion functions.
As shown in the figure below, we want to insert a 10 after 2:

First of all, we need to connect 10 and 3. Otherwise, once the connection between 2 and 3 is broken, the whole linked list will be directly separated and the position of 3 can no longer be found.

The next step is to connect 2 and 10 and disconnect 2 and 3 at the same time.

In this way, the insertion operation is completed. In fact, the essence is very simple.

void insert(int pos,List *&l,int x){
	if(pos==1){
		List *p=new List(x);
		p->next=l->next;
		l->next=p;
	}
	else insert(pos-1,l->next,x);
}

In order to find the position POS to be inserted, we can use the recursive method. Each subsequent node pos-1 will finally reach the desired position when pos=1.

Delete element

For the same linked list, suppose you delete 3 of them:

First, create a new pointer to 3, or you will not be able to free this memory after subsequent operations:

The second step is to connect 2 to 4.

Finally, releasing the new pointer is essentially releasing 3.

The code is the same. Notice that pos=2 will stop at last. This algorithm cannot delete the position of the first node.

void remove(int pos,List *&l){
	if(pos==2){
		List *p=l->next;
		l->next=l->next->next;
		delete p;
	}
	else remove(pos-1,l->next);
}

Complete thinking

A complete set of linked list is also written with 40 or 50 lines of code. The complete code is as follows:

#include<bits/stdc++.h>
using namespace std;
typedef struct List{
	int data;
	List *next;
	List(int x){
		this->data=x;
		next=NULL;
	}
};
List *lst;
void add(List *&l,int x){
	if(l==NULL){
		l=new List(x);
		return;
	}
	else add(l->next,x);
}
void write(List *l){
	if(l==NULL)return;
	else{
		printf("%d ",l->data);
		write(l->next);
	}
}
void insert(int pos,List *&l,int x){
	if(pos==1){
		List *p=new List(x);
		p->next=l->next;
		l->next=p;
	}
	else insert(pos-1,l->next,x);
}
void remove(int pos,List *&l){
	if(pos==2){
		List *p=l->next;
		l->next=l->next->next;
		delete p;
	}
	else remove(pos-1,l->next);
}
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		int x;
		scanf("%d",&x);
		add(lst,x);
	}
	while(m--){
		int k;
		scanf("%d",&k);
		if(k==1){//Insert operation
			int pos,val;
			scanf("%d%d",&pos,&val);
			insert(pos,lst,val);
			write(lst);putchar('\n');
		}
		else if(k==2){//Delete operation
			int pos;
			scanf("%d",&pos);
			remove(pos,lst);
			write(lst);putchar('\n');
		}
	}
	return 0;
}