Stack - "Data Structures and Algorithms"

Hello everyone, long time no see! ! ! I really miss it! ! !

It’s been a long time since we updated our data structure and algorithm column. Xiao Yalan has learned a lot recently, and I can’t wait to share it with my friends at station C. Now, let’s enter the world of stacks


the stack 


The concept and structure of the stack

Stack: A special linear list that only allows insertion and deletion of elements at a fixed end.

The end where data insertion and deletion operations are performed is called the top of the stack, and the other end is called the bottom of the stack.

The data elements in the stack follow the principle of LIFO (Last In First Out).

Push stack: The insertion operation of the stack is called push/push/push, and the incoming data is at the top of the stack.

Popping: The deletion operation of the stack is called popping. The output data is also on the top of the stack.

 

a few exercises

1. The initial state of a stack is empty. Now put the elements 1, 2, 3, 4, 5, A, B, C, D, and E into the stack in sequence, and then pop them out in sequence, then the order in which the elements are popped out is ( B ).

A 12345ABCDE

B EDCBA54321

C ABCDE12345

D 54321EDCBA

2. If the push sequence is 1, 2, 3, 4, and the stack can be popped during the push process, then the following impossible pop sequence is (C)

A 1,4,3,2

B 2,3,4,1

C 3,1,4,2

D 3,4,2,1

Option A: Advanced 1, then immediately out 1, then in 2 3 4, then out 4 3 2

Option B: advanced 1 2, then out 2, then in 3, out 3, in 4, out 4, and finally out 1

Option C: No matter how you enter and exit, such a combination will not appear, because: there are no two consecutive numbers

D option: advanced 1 2 3, then out 3, then in 4, out 4, then out 2, finally out 1

Implementation of the stack

The implementation of the stack can generally be implemented using an array or a linked list . Relatively speaking, the structure of the array is better. Because the cost of inserting data at the end of the array is relatively small.

 

 Next, we start to implement it with code:

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;//栈顶
	int capacity;//容量
}Stack;

This is already a routine operation, using structures and typedefs to define a stack

Initialize the stack:

// 初始化栈 
void StackInit(Stack* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->top = 0;
	pst->capacity = 0;
}

Destroy the stack:

// 销毁栈 
void StackDestroy(Stack* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

Into the stack:

The ternary operator is used here 

https://xiaoyalan.blog.csdn.net/article/details/128941939

https://xiaoyalan.blog.csdn.net/article/details/128993533

This is the relevant knowledge point of the operator written by Xiao Yalan. If you are interested, you can take a look.

// 入栈 
void StackPush(Stack* pst, STDataType x)
{
	assert(pst);
	//扩容
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}

Check if the stack is empty:

// 检测栈是否为空
bool StackEmpty(Stack* pst)
{
	assert(pst);
	if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}

Of course, this is a relatively low way of writing, let's take a look at this way of writing:

// 检测栈是否为空
bool StackEmpty(Stack* pst)
{
	return pst->top==0;
}

This way of writing is so concise, and it also realizes the functions it should have. Wouldn’t it be better?

Pop:

// 出栈 
void StackPop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	pst->top--;
}

Get the top element of the stack:

// 获取栈顶元素 
STDataType StackTop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	return pst->a[pst->top - 1];
}

Get the number of valid elements in the stack:

// 获取栈中有效元素个数 
int StackSize(Stack* pst)
{
	assert(pst);
	return pst->top;
}

Stack (stack), also known as stack, is a linear table with limited operations. A linear list that restricts insertions and deletions to the end of the list only. This end is called the top of the stack, and the other end is called the bottom of the stack. Inserting a new element into a stack is also called pushing, pushing, or pushing. It is to put the new element on top of the top element of the stack to make it a new top element of the stack; deleting an element from a stack is also called stacking or stacking. Unstack, it is to delete the top element of the stack, so that the adjacent element becomes the new top element of the stack.

 To understand this concept, we must first understand the original meaning of "stack", so as to grasp the essence. Stack, a place for storing goods or accommodation for passengers, can be extended to warehouses and transfer stations, so when it is introduced into the computer field, it refers to the place where data is temporarily stored, so there is a saying of entering and exiting the stack.


First of all, reading and inserting (pushing) push and popping the data content in the system or data structure stack are two different things.

Pushing is to add data, and popping is to delete data. These operations can only be performed from the top of the stack, which is the lowest address, as the constraint interface interface, but reading the data in the stack is casual, and there is no such thing as interface constraints. Many people misunderstand this concept and thus become confused about the stack. The system stack also plays the role of a cross-component interaction media area in the computer architecture, that is, the communication channel between the cpu and the memory. The cpu only linearly reads and executes from the stack entry specified by the system for our own application programs. Instructions, using a vivid word to describe it is pipeline (pipeline, pipeline). For details on the internal interaction of the cpu, refer to the introduction to the concept of EU and BIU.


As a data structure, a stack is a special linear table that can only perform insertion and deletion operations at one end. It stores data according to the principle of last-in-first-out. The data that enters first is pushed to the bottom of the stack, and the last data is on the top of the stack. When data needs to be read, data is popped from the top of the stack (the last data is read out first). The stack has a memory function, and there is no need to change the bottom pointer of the stack during the insertion and deletion operations of the stack.


Stacks are special linear lists that allow insertion and deletion at the same end. The end that allows insertion and deletion operations is called the top of the stack (top), and the other end is the bottom of the stack (bottom); the bottom of the stack is fixed, while the top of the stack is floating ; when the number of elements in the stack is zero, it is called an empty stack . Insertion is generally called push (PUSH), and deletion is called pop (POP). A stack is also called a first-in last-out list.
The stack can be used to store breakpoints when a function is called, and the stack is used when doing recursion.

The above definitions are interpretations in classical computer science.


In a computer system, a stack is a dynamic memory area with the above properties. Programs can push data onto the stack, or pop data off the top of the stack. On i386 machines, the top of the stack is located by a register called esp. The operation of pushing the stack reduces the address of the top of the stack, and the operation of popping increases the address of the top of the stack.


The stack plays an important role in the operation of the program. The most important thing is that the stack saves the maintenance information needed for a function call, which is often called a stack frame or an active record. A stack frame generally contains the following information:
1. The return address and parameters of the function
2. Temporary variables: including non-static local variables of functions and other temporary variables automatically generated by the compiler.


Test the functionality of this code:

void testStack1()
{
	Stack st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);
	printf("栈顶元素:%d\n", StackTop(&st));
	printf("栈中元素个数:%d\n", StackSize(&st));
	StackPop(&st);
	printf("栈顶元素:%d\n", StackTop(&st));
	StackPush(&st, 5);
	StackPush(&st, 6);
	while (!StackEmpty(&st))
	{
		printf("栈顶元素:%d\n", StackTop(&st));
		StackPop(&st);
	}
	StackDestroy(&st);
}
int main()
{
	testStack1();
	return 0;
}


The source code is as follows:

Contents of Stack.h:

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;//栈顶
	int capacity;//容量
}Stack;

// 初始化栈 
void StackInit(Stack* pst);

// 销毁栈 
void StackDestroy(Stack* pst);

// 入栈 
void StackPush(Stack* pst, STDataType x);

// 出栈 
void StackPop(Stack* pst);

// 获取栈顶元素 
STDataType StackTop(Stack* pst);

// 获取栈中有效元素个数 
int StackSize(Stack* pst);

// 检测栈是否为空 
bool StackEmpty(Stack* pst);

Contents of Stack.c:

#include"Stack.h"
// 初始化栈 
void StackInit(Stack* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->top = 0;
	pst->capacity = 0;
}
// 销毁栈 
void StackDestroy(Stack* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}
// 入栈 
void StackPush(Stack* pst, STDataType x)
{
	assert(pst);
	//扩容
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
// 检测栈是否为空
bool StackEmpty(Stack* pst)
{
	assert(pst);
	if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}
	//return pst->top==0;
}
// 出栈 
void StackPop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	pst->top--;
}
// 获取栈顶元素 
STDataType StackTop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	return pst->a[pst->top - 1];
}

// 获取栈中有效元素个数 
int StackSize(Stack* pst)
{
	assert(pst);
	return pst->top;
}

Alright, this is the end of the stack knowledge shared by Xiao Yalan today, let’s continue to learn data structures and algorithms! ! !

 

Guess you like

Origin blog.csdn.net/weixin_74957752/article/details/130732994