Chapter 2 of "Aha Algorithm" - Queue Stack Linked List

insert image description here


foreword

In the previous section, we learned the quick sort bubble sort bucket sort in the sorting algorithm, so the main learning content of this section is the knowledge of the relevant data structure of the queue stack linked list


1. Basic knowledge of data structure (connection knowledge)

Based on the study of this book, some algorithmic noobs and even primary school students are learning, so I would like to add some basic knowledge of data structure to everyone, so that everyone can better understand the knowledge in this section

1. What does "first in, last out" in the stack mean?

The stack has two main operations for data management:

  1. Push stack: The insertion operation of the stack is called push/push/push, and the stack is pushed from the top of the stack.
  2. Popping: The deletion operation of the stack is called popping, and the stack is popped from the top of the stack.
    insert image description here

2. The definition of the stack
The stack only allows the operation of inserting and deleting elements in a fixed section. The end that performs data insertion and deletion operations is called the top of the stack, and the end that does not perform operations is called the bottom of the stack. The elements in the stack follow the principle of last in first out (LIFO - Last In First Out). That is, first in last out, last in first out

3.
The image metaphor of the difference between a stack and a queue is that a stack is like a bullet, and the first to go in is shot out at the end, while the queue is the inside of the queue, first-come, first-served.

After reading these, if you want to know more about queues and stacks, you can read my two blogs below to learn
[data structure] explain queues in simple terms with a thousand words (original code attached | super detailed explanation)

【Data structure】Thousand words in-depth explanation stack (with original code | super detailed explanation)

Two, the queue

queue definition

队列:A special linear table that only allows inserting data operations at one end and deleting data operations at the other end . The queue has first-in-first-out

FIFO(First In First Out)Into the queue: the end of the insertion operation is called the tail of the queue Out of the queue: the end of the deletion operation is called the head of the queue

The data structure diagram is as follows:
insert image description here
the head of the queue (head) deletes data, which is called "out of the queue" and the
tail of the queue (tail) inserts data, which is called "entry into the queue"
. When there is no element in the queue (head == tail), it is called empty queue

topic description

At the beginning of the new semester, Xiao Hum and Xiao Ha sat at the same table, and then Xiao Hun asked Xiao Ha what his QQ number was, but Xiao Ha didn’t give others his QQ number easily, so he gave a string of mysterious numbers, but the numbers are regular numbers

The rule is to delete the first number first, then put the second number at the end of the string, then delete the third number, and put the fourth number at the end...

Until the last number is left, the last number is also deleted. Connecting the deleted numbers together is Xiaoha's QQ number. The string of numbers that Xiaoha encrypted for him is "920430714", what is Xiaoha's QQ number?

problem solving ideas
insert image description here
insert image description here

The operation of deleting a number at the head of the team is head++
The operation of adding a number at the end of the team is q[tail]=x , tail++

Now there are 9 numbers, after putting 9 numbers into the queue, head == 1, tail == 10, at this time the number between head and tail is the "valid" number in the current queue

code show as below

//方法一:
#include<iostream>
using namespace std;
int main()
{
    
    
	int q[102]={
    
    0,6,3,1,7,5,8,9,2,4},head,tail;
	//初始化队列
	head=1;//指向第一个
	tail=10;//指向最后一个的下一个
	while(head<tail)//队列不为空
	{
    
    
		//打印队首
		printf("%d ",q[head]);
		head++;//队首出队 
		
		//先将新队首得数添加到队尾
		q[tail]=q[head];
		tail++;
		//再将队首出队 
		head++; 
	}
	return 0;
}

sample instance

输入:6 3 1 7 5 8 9 2 4
输出:6 1 5 9 4 7 2 8 3

Encapsulate the three basic elements of the queue (an array and two variables) into a structure type. In fact, the first method should not be used in the algorithm competition.

//方法二

#include<iostream>
using namespace std;
struct queue
{
    
    
	int data[100];
	int head;
	int tail;
};
int main()
{
    
    
	struct queue q;
	int i;
	//初始化队列
	q.head=1;
	q.tail=1;
	for(int i=1;i<=9;++i)
	{
    
    
		//依次向队列插入9个数
		cin>>q.data[q.tail];
		q.tail++; 
	}
	while(q.head<q.tail)
	{
    
    
		//打印队首并将队首出队
		cout<<q.data[q.head]<<" ";
		q.head++;
		q.data[q.tail]=q.data[q.head];
		q.tail++;
		q.head++; 
	}
	return 0;
}

Three, the stack

Stack last in first out, there are many examples in life:

1. To browse the webpage and return to a previous webpage, you need to click the back button step by step
2. Load the bullet into the magazine, the last loaded bullet is the first to be fired, or the first to be ejected
3. And For example, in a small bucket, the diameter of the small bucket can only hold one ball, and put in balls 2, 1, and 3 in sequence. If you want to take out ball 2, you must first take out ball 3, then take out ball 1, and finally In order to take the No. 2 ball that was put in first

insert image description here
The main problem in this section of the stack is to judge the palindrome string. In fact, I have written this topic as early as when I was learning C language. Niuke has this topic.

Problem-solving ideas:
Divide the string into two, set the midpoint as mid, push the string to the left of mid into the stack, and then let the letters in the stack match the characters after mid after being pushed into the stack, and set Top , every time the match is successful Top–, finally check whether Top is 0, if it is 0, it means it is a palindrome, otherwise it is not a palindrome character

Operation of stacking: s[++top] = a[i];
Get the string length len through strlen(a), mid = len / 2 - 1;

code show as below:

#include<iostream>
#include<cstring>
using namespace std;

char a[110],s[110];
int len,mid,next,top;

int main()
{
    
    
	cin.get(a,110);//读入字符串 
	len=strlen(a);//求字符串长度 
	mid=len/2-1;//求字符串的中点
	//入栈操作
	for(int i=0;i<=mid;++i)
	{
    
    
		s[++top]=a[i];
	}
	//判断字符串的长度是奇数还是偶数,并找出需要进行字符匹配的下标
	if(len%2==0) next=mid+1;
	else next=mid+2; 
	
	//开始匹配
	for(int i=next;i<=len-1;++i)
	{
    
    
		if(a[i]!=s[top]) break;
		top--;
	}
	
	if(top==0)	cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	return 0;
}

sample instance

输入:nihaooahin
输出:Yes

Let's explain the idea of ​​​​not using the stack:

double pointer arithmetic, respectively pointing to the left and right sides of the string to go towards each other, one by one matching, when the characters pointed by the two pointers are different, output NO, when the two pointers meet or pass through each other, output Yes

code show as below:

#include<iostream>
#include<cstring>
using namespace std;
char a[110];
int is_huiwen(int left,int right)
{
    
    
	while(left<right)
	{
    
    
		if(a[left++]!=a[right--]) return 0;
		else continue;
	}
	return 1;
}
int main()
{
    
    
	cin.get(a,110);
	int right=strlen(a)-1;
	if(is_huiwen(0,right)) cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	return 0;
}

4. Linked list

Definition of linked list

链表It is an 物理存储结构upper 非连续and 非顺序higher storage structure, and the data elements are realized 逻辑顺序through 链表中的指针the link order.

insert image description here

Implement linked list

Use pointers and dynamic memory allocation function malloc to achieve

1. For pointers
, see the blog for details: C language—beginners of pointers—summary

2. The malloc function
1 malloc(sizeof(int))
is equivalent to malloc(4); apply to allocate a memory space of 4 bytes from the memory
2 Now we have successfully applied for a space of 4 bytes from the memory to store a Integer, how to operate on this space?
This requires a pointer to point to this space, that is, to store the first address of this space
3 (int *) malloc () function return type is void * type, indicating an undetermined type of pointer, which can be cast to any other type of pointer , here we need to force conversion to integer, so it is (int *)

int *p; //定义指针p
p = (int *)malloc(sizeof(int));

The malloc() function dynamically applies for space:

#include<iostream>
#include<cstdlib> //malloc()
using namespace std;
int main()
{
    
    
    int *p; //定义指针p
    //指针p获取动态分配的内存地址
    p = (int *)malloc(sizeof(int));
    *p = 10; //向p所指向的内存存入10
    cout<<*p<<endl; //输出p指向内存中的值
    return 0;
}

Each node is composed of two parts. The left part stores specific values, and the right part stores the address of the next node (called the successor pointer). Here we define a structure type to store this node. See my data structure blog [data]
insert image description here
for details Structure] 10,000 characters explain the single-linked list in simple terms (with original code | super detailed explanation)

Problem: Create a linked list

#include<iostream>
#include<cstdlib> //malloc()
using namespace std;
struct node
{
    
    
    int data;
    struct node *next;
};
int main()
{
    
    
    struct node *head, *p, *q, *t;
    int i, n, a;
    cin>>n;
    head = NULL; //头指针初始为空
    for(i = 1; i <= n; ++i) {
    
    
        cin>>a;
        //动态申请一个空间存放节点,临时指针p指向这个节点
        p = (struct node *)malloc(sizeof(struct node));
        p->data = a; //数据存储到数据域
        p->next = NULL; //后继指针指向空
        if(head == NULL)
            head = p; //第一个节点让头指针指向
        else
            q->next = p; //否则上一节点后继指针指向当前节点
        q = p; //上一节点指针指向当前节点
    }
 
    //输出链表中所有数
    t = head;
    while(t != NULL) {
    
    
        cout<<t->data<<" ";
        t = t->next; //继续下一节点
    }
    return 0;
}

Problem: inserting data

#include<iostream>
#include<cstdlib> //malloc()
using namespace std;
 
//创建一个结构体表示节点
struct node
{
    
    
    int data;
    struct node *next;
};
 
int main()
{
    
    
    struct node *head, *p, *q, *t; //p,q,t都是临时指针
    int i, n, a;
    cin>>n; //n个数
    head = NULL; //头指针初始为空
    for(i = 1; i <= n; ++i) {
    
    
        cin>>a;
        //动态申请空间存放一个节点,临时指针p指向该节点
        p = (struct node *)malloc(sizeof(struct node));
        p->data = a;
        p->next = NULL; //当前节点下一节点为空
        if(head == NULL)
            head = p; //若为第一个创建的,头指针指向该节点
        else
            q->next = p; //上一节点后继指针指向当前节点
        q = p; //指针q指向当前节点
    }
 
    cin>>a; //待插入的数
    t = head; //从链表头部开始遍历
    while(t != NULL) {
    
    
        if(t->next == NULL || t->next->data > a) {
    
    
            p = (struct node *)malloc(sizeof(struct node));
            p->data = a;
            //新增节点后继指针指向当前节点后继指针所指向的节点
            p->next = t->next;
            t->next = p; //当前节点后继指针指向新增节点
            break; //插入完退出循环
        }
        t = t->next; //继续下一节点
    }
 
    //输出链表所有数
    t= head;
    while(t != NULL) {
    
    
        cout<<t->data<<" ";
        t = t->next; //继续下一节点
    }
    return 0;
}

Summarize

Go here first and continue to add later

Guess you like

Origin blog.csdn.net/congfen214/article/details/131754463