[Data structure and algorithm] Use the structure of the array to realize the linked list (one-way or two-way)

Above, we have realized the queue and circular queue through the structure of the structure. We may have only learned to use the structure to realize the data structure of the linked list, queue, stack and so on in the teaching of other teachers. In this article, I want to tell Yours is, we can use the structure of arrays to implement linked lists, monotonic stacks, and monotonic queues

Table of contents

foreword

1. The benefits of using an array structure

1. Advantages and disadvantages of arrays

2. Advantages and disadvantages of linked list

3. Summary

Second, use arrays to implement linked lists

1. Understanding structure and initialization

2. Insert x into the head node

3. Insert x to the position after the kth inserted value

4. Delete the node inserted for the kth time

3. Complete code demo

Fourth, the array realizes the doubly linked list

1. Initialization

2. Insert x to the right of the kth inserted point

3. Delete the kth point

Five, complete code


foreword

Did you realize the form of the linked list before, is this a structure to achieve it?

typedef struct ListNode {
	int data;
	struct ListNode* next;
}List;

But if I tell you that only these two arrays are needed to simulate a linked list, would you believe it! ! !

head	表示头节点
e[N]	表示存储结点数值的数组
ne[N]	表示结点的下一个结点的位置
idx   表示当前存储元素的位置   当前存储到哪里了就是

 Next, let's implement a singly linked list and a doubly linked list

1. The benefits of using an array structure

In the process of our daily study, what the teacher taught us is a linked list implemented in the form of a structure, but, for example, if we want to create 100,000 nodes, in this case, using a structure, the time is too long and the space is too large Large, in contrast to the array, it appears to be very advantageous.

1. When working on the algorithm, using the form of an array to simulate the linked list will make the calculation speed faster, which is more suitable for children who write algorithms and play games.

2. If the written test is suitable, it will be faster to create and realize the basic functions of the linked list, insert and delete elements, and directly find the required elements according to the subscript, etc.

Let's take a look at the advantages and disadvantages of arrays and linked lists.

1. Advantages and disadvantages of arrays

Know the array:

An array is a linear structure, and the storage space is continuous in memory (physically continuous). Whenever an array is created, a space of a specified size must be applied for first. (One time application can specify the size of the space)

advantage:

Due to the feature of continuous memory, the access speed of the array is very fast. After the index subscript, the access with time complexity of O(1) can be realized.

shortcoming:

1. When deleting and inserting at any position, it will involve the movement of some elements. In this way, the time complexity of our deletion and insertion at any position of the array is O(n).

for example:

1> Insert data after point i, then you need the i+1 position and the following elements, move one bit backward as a whole (for loop operation), and then put the inserted data at the i+1 position

2> To delete elements after point i, then it is necessary to move the elements after i+1 and after by one bit as a whole, and reduce the total number of elements by one

The above are the advantages and disadvantages of arrays, which can be accessed quickly, reaching O(1), but when deleting and inserting elements arbitrarily, it will take time to reach O(n).

2. Advantages and disadvantages of linked list

Know linked list

1. The linked list is also a linear structure, but its storage space is discontinuous (physically discontinuous, logically continuous), the length of the linked list is uncertain and supports dynamic expansion. Every time you insert an element, you need to apply for a new node, then assign a value, and insert it into the linked list.

Advantages:
When inserting or deleting data, you only need to change the pointing of the pointer. You don’t need to move parts as a whole like an array. The whole process does not involve the migration of elements. Therefore, the time complexity of inserting and deleting operations in linked lists is O(1)

shortcoming:

When looking for the numerical field of a node at any position, it needs to be traversed, and the time complexity is O(n)

But when we insert or delete an element at any position, we need to find the node position of the specified element, so in combination, the insertion and deletion of the linked list is still O(n).

3. Summary

Regardless of the array or the linked list, the time complexity of the search is O(n), and the search must be traversed one by one until the data that meets the conditions is found, so for the linked list, if it is not given, the address of the pointer is just to insert and delete the first When N-bit elements are added, the combined time complexity is O(n).

But if we implement the linked list in the form of an array, is it easier to insert and delete the specified element position? When inserting and deleting an element at the Nth position, the time complexity of O(1) is directly found. The position node, and then because the deletion and insertion of the linked list are all O(1), the overall time complexity of the entire deletion or insertion operation is O(1), which is much faster than the ordinary linked list.

Second, use arrays to implement linked lists

1. Understanding structure and initialization

Let's first understand the preparations for initialization from the diagram

It will be easier to understand when we use c++, because c++ supports variables to define arrays

Initialization code:

//使用c++更简单,先用c++的形式实现
const int N = 100010;
int head, e[N], ne[N], idx; //全局变量
void init() {
	head = -1;
	idx = 0;//进行初始化的操作,idx为当前链表中(数组)最后一个元素(末尾),下标位置
}

2. Insert x into the head node

is the so-called head insertion in the linked list

Graphic:

In fact, it is the same as the header of a normal linked list, except that the next pointer of the process is replaced by a ne[N] array, which records the value of the next node.

code show as below:

void add_to_head(int x) {
	e[idx] = x;//将x数值存入到e[]数组中
	ne[idx] = ne[head];//将idx新插入的结点的下一个位置存储到ne[idx]中  ,全局变量 ne以及n数组初始化为0
	head = idx;
	idx++;
}

3. Insert x to the position after the kth inserted value

Graphic:

We want to explain a problem. The value stored in the ne[N] array does not need to be managed, because no matter whether it is add or remove, insert or delete nodes, it will not be repeated. In fact, e[ne[head]] It is to get the value of the next node of the head node, and the ne[] array is only used as a subscript. 

We insert x at the position after the k-th insertion, but at the same time, the idx at this time becomes the new k-th insertion data subscript, that is, it is inserted again at the position after the k-th insertion value x, is actually inserted after the last newly inserted node

Graphic:

code show as below:

//在第k个插入的数字之后插入数据
void add(int k, int x) {
	e[idx] = x;
	ne[idx] = ne[k];
	ne[k] = idx;
	idx++;
}

4. Delete the node inserted for the kth time

//将下标为k的点后面的点删掉
void remove(int k, int ne[]) {
	ne[k] = ne[ne[k]];//表示k的下一个位置(ne)为下一个位置的下一个位置,这样跳过了原来的ne[k]结点
}//使用的时候应该是  删除的是k之后的点

Just skip directly, similar to a linked list

3. Complete code demo

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>


const int N = 100010;
int n, e[N], ne[N], idx, head;


//初始化
void init() {
	head = -1;
	idx = 0;
}

//头插
void add_to_head(int x) {
	e[idx] = x;
	ne[idx] = head;
	head = idx;
	idx++;
}

//在第k个插入的数字之后插入数据
void add(int k, int x) {
	e[idx] = x;
	ne[idx] = ne[k];
	ne[k] = idx;
	idx++;
}
//删除第k的插入的数据
void remove(int k) {
	ne[k] = ne[ne[k]];
}

int main()
{
	init();
	add_to_head(1);
	add_to_head(2);
	add_to_head(3);
	add_to_head(4);
	add_to_head(5);
	add(2-1, 10);
	add(2-1, 2);
	add(2-1, 3);
	add(2-1, 4);
	add(2-1, 5);
	add_to_head(50);
	for (int i = head; i != -1; i=ne[i]) {
		printf("%d ", e[i]);
	}
	printf("\n");
	for (int i = head; i != -1; i = ne[i]) {
		printf("%d ", ne[i]);
	}
	return 0;
}

Fourth, the array realizes the doubly linked list

1. Initialization

//初始化
// e[]表示节点的值,l[]表示节点的左指针,r[]表示节点的右指针,idx表示当前用到了哪个节点
int m;
const int N = 100010;
int e[N], l[N], r[N], idx;
void init() {
	//0表示为左端点,1表示为右端点
	r[0] = 1;
	l[1] = 0;
	idx = 2;//从2开始
}

We set, use e[N] array to record data, and use l[N], r[N] arrays to represent the left and right pointers of nodes. At the beginning, 0 represents the left endpoint, 1 represents the right endpoint, and then r, r[N] l Two array records, the value subscript starts from 2

e[] indicates the value of the node, l[] indicates the left pointer of the node, r[] indicates the right pointer of the node, and idx indicates which node is currently used

2. Insert x to the right of the kth inserted point

//在第k次插入的点的右边插入x;

void add(int k, int x) {
	e[idx] = x;//数值x给当前idx位置的e数组存储
	r[idx] = r[k];//将新节点的左右两端分别连接k的后一个结点r[k]和k本身
	l[idx] = k;
	l[r[k]] = idx;//然后将k的右端点的左端点连接idx
	r[k] = idx;//最后将k的右端点连接idx
}

3. Delete the kth point

//删除第k个点
void remove(int k) {
	//就是将k的左端点和右端点相互连接
	l[r[k]] = l[k];
	r[l[k]] = r[k];
}

Five, complete code

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<assert.h>
//使用数组的形式实现双向链表


//e[N]	表示存储结点的数值
//l[N]	表示当前结点的左结点位置
//r[N]	表示当前结点的右节点位置
//idx	表示当前结点存储的位置

//初始化
int m;
const int N = 100010;
int e[N], l[N], r[N], idx;
void init() {
	//0表示为左端点,1表示为右端点
	r[0] = 1;
	l[1] = 0;
	idx = 2;//从2开始
}

//在第k次插入的点的右边插入x;

void add(int k, int x) {
	e[idx] = x;//数值x给当前idx位置的e数组存储
	r[idx] = r[k];//将新节点的左右两端分别连接k的后一个结点r[k]和k本身
	l[idx] = k;
	l[r[k]] = idx;//然后将k的右端点的左端点连接idx
	r[k] = idx;//最后将k的右端点连接idx
}

//删除第k个点
void remove(int k) {
	//就是将k的左端点和右端点相互连接
	l[r[k]] = l[k];
	r[l[k]] = r[k];
}

Guess you like

Origin blog.csdn.net/qq_63319459/article/details/128854520