Stack and Queue

Table of contents

1. Stack

1. Concept and structure of stack

1.1 Concept of stack

1.2 Stack structure diagram

2. Implementation of stack

2.1 Structure of stack that supports dynamic growth

2.2 Push (push)

2.3 Pop out

2.4 Code implementation that supports dynamically growing stacks

2. Queue

1. Concept and structure of queue

1.1 The concept of queue

1.2 Structural diagram of queue

2. Implementation of queue

2.1 Queue structure

2.2 The end of the queue enters the queue

2.3 The head of the queue dequeues

2.4 Queue code implementation

1. Stack

1. Concept and structure of stack

1.1 Concept of stack

        The stack is a special linear list. The stack only allows inserting and deleting data at a fixed end. The insertion operation of the stack is called push (pushing), and the deletion operation of the stack is called destack. The end where data insertion and deletion operations are performed is called the top of the stack, and the other end is Bottom of the stack. The elements in the stack follow the first-in-last-out principle.

1.2 Stack structure diagram

2. Implementation of stack

        Stacks are generally divided into static stacks and stacks that support dynamic growth. Static stacks are not practical because the stack space size is fixed, so we only implement code for stacks that support dynamic growth:

2.1 Structure of stack that supports dynamic growth

        The implementation of the stack is generally implemented in the form of an array. A stack that supports dynamic growth means opening a dynamic array a to store data. When the stack capacity is full, it can be easily expanded.

// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;		// 栈顶
	int capacity;  // 容量 
}Stack;

2.2 Push (push)

        Each time the stack is pushed, first check whether the stack capacity is full, and then decide whether it needs to be expanded. The pushed element becomes the new top of the stack.

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

2.3 Pop out

        After popping, the new top of the stack becomes the previous element of the top of the stack before popping.

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

2.4 Code implementation that supports dynamically growing stacks

#pragma once
#include<assert.h>
#include<stdlib.h>
#include<stdio.h>

// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;		// 栈顶
	int capacity;  // 容量 
}Stack;

// 初始化栈 
void StackInit(Stack* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;//top指向栈顶的下一个位置,对top的操作需要是:先使用后++
	ps->capacity = 0;
}

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

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

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

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

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->top == 0;
}

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

2. Queue

1. Concept and structure of queue

1.1 The concept of queue

        Different from the concept of a stack, a queue only allows data insertion operations at one end and deletion data operations at the other end. The end that performs data insertion operations is the tail of the queue, and the end that performs data deletion operations is the head of the queue. A queue is a special linear list that follows the first-in, first-out principle.

1.2 Structural diagram of queue

2. Implementation of queue

2.1 Queue structure

        The implementation of queue is generally better to use the structure of linked list:

Code:

// 队列成员节点结构
typedef int QDataType;
typedef struct QListNode
{
	struct QListNode* next;
	QDataType data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* front;
	QNode* rear;
	int size;
}Queue;

Simplified diagram:

2.2 The end of the queue enters the queue

Code:

// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{
	assert(q);
	
	QNode* NewNode = (QNode*)malloc(sizeof(QNode));
	if (NewNode == NULL)
	{
		perror("malloc:");
		return;
	}
	NewNode->data = data;
	NewNode->next = NULL;
	if (q->size == 0)
	{
		q->front = q->rear = NewNode;
	}
	else
	{
		q->rear->next = NewNode;
		q->rear = q->rear->next;
	}
	q->size++;
}

Simplified diagram:

2.3 The head of the queue dequeues

Code:

// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	//assert(!QueueEmpty(q));
	if (q->front ==q->rear)
	{
		if (q->front == NULL)
		{
			return;
		}
		else
		{
			free(q->front);
			q->front = q->rear = NULL;
		}
	}
	else
	{
		QNode* Tmp = q->front;
		q->front = Tmp->next;
		free(Tmp);
		Tmp = NULL;
	}
	q->size--;
}

Simplified diagram:

2.4 Queue code implementation

#pragma once
#include<assert.h>
#include<stdlib.h>
#include<stdio.h>

// 链式结构:表示队列成员节点
typedef int QDataType;
typedef struct QListNode
{
	struct QListNode* next;
	QDataType data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* front;
	QNode* rear;
	int size;
}Queue;

// 初始化队列 
void QueueInit(Queue* q)
{
	assert(q);
	q->front = q->rear = NULL;
	q->size = 0;
}

// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{
	assert(q);
	
	QNode* NewNode = (QNode*)malloc(sizeof(QNode));
	if (NewNode == NULL)
	{
		perror("malloc:");
		return;
	}
	NewNode->data = data;
	NewNode->next = NULL;
	if (q->size == 0)
	{
		q->front = q->rear = NewNode;
	}
	else
	{
		q->rear->next = NewNode;
		q->rear = q->rear->next;
	}
	q->size++;
}

// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	//assert(!QueueEmpty(q));
	if (q->front ==q->rear)
	{
		if (q->front == NULL)
		{
			return;
		}
		else
		{
			free(q->front);
			q->front = q->rear = NULL;
		}
	}
	else
	{
		QNode* Tmp = q->front;
		q->front = Tmp->next;
		free(Tmp);
		Tmp = NULL;
	}
	q->size--;
}

// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	return q->front->data;
}

// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	return q->rear->data;
}

// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{
	assert(q);
	return q->size;
}

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{
	assert(q);
	return q->size == 0 ? 1 : 0;
}

// 销毁队列 
void QueueDestroy(Queue* q)
{
	assert(q);
    while(!QueueEmpty(q))
    {
        QueuePop(q);
    }
}

Guess you like

Origin blog.csdn.net/libj2023/article/details/132636026