Implementation of data structure array stack

Insert image description here

Hello, today we will implement an array stack. After learning this, we will go one step further.

1. Stack

Stack concept

A stack is a special linear list that only allows insertion and deletion of elements at a fixed end.
Insertion and deletion of data are only implemented at the top of the stack, and the other end is the bottom of the stack.
The elements of the stack are last-in-first-out.

Pushing the stack: Data entering the stack is called pushing
the stack. Popping: Deleting data from the stack is called popping the stack.

Let’s draw a schematic diagram for everyone to understand better.

Insert image description here

This process is called pop out of the stack

Our above-mentioned processes are all implemented on the top of the stack, and cannot be deleted or added from any position like sequence lists and singly linked lists. However, this is the nature of the stack, and we will talk about its role later.

To implement the stack, we can use linked lists to generate nodes to link them, but we can also use array subscript access, similar to methods such as sequence tables. Which of these
two methods is better? Let's compare.

Because of the nature of the stack, we are not allowed to pop or push from the top of the stack. If we implement it in a linked list, there will inevitably be a problem, that is, our time complexity is O(N) and we need to traverse the array once, so The stack seems to become "earthy", so using arrays can improve efficiency faster.

2. Definition of stack

typedef int StackDataType;
#define N 100
struct Stack
{
    
    
	StackDataType arry[N];
	StackDataType top;
};

This is a static stack. We talked about the shortcomings of the static stack during the sequence table. The biggest disadvantage is that it cannot open up space. 100 can only store 100 data at most. If I only use 10 int space, it will be wasted. If I want to store 1,000 pieces of data and we don't have enough space, this will cause a series of problems, so let's change it into a dynamic stack and let's implement it.

typedef int StackDataType;
typedef struct Stack
{
    
    
	StackDataType* arry;
	int top;
	int capacity;
}Stack;

With the structure still the same as before, let's implement the interface function and get started!
Initialization stack

void StackInit(Stack* pst)
{
    
    
	assert(pst);
	pst->arry = NULL;
	pst->capacity = pst->top = 0;
}

Everyone must know how to initialize the stack.

destroy


void StackDestory(Stack* pst)
{
    
    
	assert(pst);
	free(pst->arry);
	pst->capacity = pst->top = 0;
	
}

Determine whether the stack is empty

bool StackEmpty(Stack* pst)
{
    
    
	assert(pst);
	return pst->top == 0;
}

Now we have to implement a push method to the stack. When pushing the stack, we need to check whether our memory space is full. The same as the sequence table. If it is full, we need to expand it. Therefore, when pushing onto the stack, you need to determine whether the space is full.

void StackPush(Stack* pst, StackDataType x)
{
    
    
	assert(pst);
	if (pst->capacity == pst->top)
	{
    
    
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		StackDataType* tmp = (StackDataType*)realloc(pst->arry, sizeof(int) * newcapacity);
		if (tmp == NULL)
		{
    
    
			printf("realloc fail\n");
			exit(-1);
		}
		pst->arry = tmp;
		pst->capacity = newcapacity;
	}
	pst->arry[pst->top - 1] = x;
	pst->top++;

}

This is exactly the same as the end insertion of our sequence table. Now you will definitely find it much simpler.
When there is pushing into the stack, there is popping out of the stack.

void StackPop(Stack* pst)
{
    
    
	assert(pst);
	if (pst->top > 0)
	{
    
    
		pst->top--;
	}
}

Because we wrote a function above to determine whether the number is empty, we can also write it as

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

Return the top data of the stack

StackDataType StackTop(Stack* pst)
{
    
    
	assert(pst);
	return pst->arry[pst->top - 1];
}

Count the number of people in the stack

int StackSize(Stack* pst)
{
    
    
	assert(pst);
	return pst->top;
}

Complete code

#pragma once

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
//typedef int StackDataType;
//#define N 100
//struct Stack
//{
    
    
//	StackDataType arry[N];
//	StackDataType top;
//};


typedef int StackDataType;
typedef struct Stack
{
    
    
	StackDataType* arry;
	int top;
	int capacity;
}Stack;

void StackInit(Stack* pst);

void StackDestory(Stack* pst);

bool StackEmpty(Stack* pst);

void StackPush(Stack* pst, StackDataType x);

void StackPop(Stack* pst);

StackDataType StackTop(Stack* pst);

int StackSize(Stack* pst);

#include"Stack.h"


void StackInit(Stack* pst)
{
    
    
	assert(pst);
	pst->arry = NULL;
	pst->capacity = pst->top = 0;
}

void StackDestory(Stack* pst)
{
    
    
	assert(pst);
	free(pst->arry);
	pst->capacity = pst->top = 0;
	
}

bool StackEmpty(Stack* pst)
{
    
    
	assert(pst);
	return pst->top == 0;
}

void StackPush(Stack* pst, StackDataType x)
{
    
    
	assert(pst);
	if (pst->capacity == pst->top)
	{
    
    
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		StackDataType* tmp = (StackDataType*)realloc(pst->arry, sizeof(int) * newcapacity);
		if (tmp == NULL)
		{
    
    
			printf("realloc fail\n");
			exit(-1);
		}
		pst->arry = tmp;
		pst->capacity = newcapacity;
	}
	pst->arry[pst->top - 1] = x;
	pst->top++;

}

void StackPop(Stack* pst)
{
    
    
	assert(pst);
	if (pst->top > 0)
	{
    
    
		pst->top--;
	}
}

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

StackDataType StackTop(Stack* pst)
{
    
    
	assert(pst);
	return pst->arry[pst->top - 1];
}

int StackSize(Stack* pst)
{
    
    
	assert(pst);
	return pst->top;
}

There are also many applications of the stack, which I will share with you later. See you next time.

Guess you like

Origin blog.csdn.net/2301_76895050/article/details/132515410