栈与队列简介

@[TOC](文章目录)

目录

1.栈

(1)栈的概念及结构

(2)栈的实现

2.队列

(1)队列的概念及结构

(2)队列的实现


1.栈

(1)栈的概念及结构

        栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

栈与队列简介_第1张图片
       出栈:栈的删除操作叫做出栈。出数据也在栈顶。

 栈与队列简介_第2张图片

(2)栈的实现

       栈是一种基于顺序表或链表的结构,如果选用数组的话,这里不存在什么难题,但如果是选用链表的话,就需要注意一件事,在栈里,我们可以操作的只有栈顶的数据,使用单链表的话,要解决在删掉栈顶元素后,要让栈顶指针指向新的栈顶,因为单链表只允许单向访问,所以我们使用单链表时需要进行改变。

方法一:把单链表改成双向链表;

方法二:让栈顶作为链表的头,栈底作为链表的尾,压栈相当于链表的头插。

首先设计栈的结构体,动态的栈比较实用。

​
typedef int STDataType;
 
typedef struct stack
{
	STDataType* a;   //模拟栈的数组
	int top;         //栈顶数据的下一个位置
  	int capacity;    //栈的容量
};

​

然后根据栈的特点,写基本栈的操作。

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

// 入栈 
void StackPush(Stack* ps, STDataType data); 

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

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

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

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps); 

// 销毁栈 
void StackDestroy(Stack* ps); 
// 初始化栈 
void StackInit(Stack* ps)
{
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}
// 入栈 
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		int newCapacity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);
		ps->a = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
		if (ps->a == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->capacity = newCapacity;
	}
	ps->a[ps->top] = data;
	ps->top++;
}
// 出栈 
void StackPop(Stack* ps)
{
	assert(ps);
	assert(ps->top > 0);
	ps->top--;
}

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

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

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

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

2.队列

(1)队列的概念及结构

        队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头

栈与队列简介_第3张图片

(2)队列的实现

        队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。

  队列的结构体

typedef int QTDataType;

//队列的每一个节点
typedef struct queuenode
{
	QTDataType data;
	struct queue* next;
}QueueNode;

//整个队列
typedef struct queue
{
	QueueNode* front;
	QueueNode* rear;
};

然后根据队列的特点,写基本队列的操作。

// 初始化队列
void QueueInit(Queue * q);

// 队尾入队列 
void QueuePush(Queue* q, QTDataType data);

// 队头出队列 
void QueuePop(Queue* q);

// 获取队列头部元素 
QTDataType QueueFront(Queue* q);

// 获取队列队尾元素 
QTDataType QueueBack(Queue* q);

// 获取队列中有效元素个数 
int QueueSize(Queue* q);

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);

// 销毁队列 
void QueueDestroy(Queue* q);

// 创建节点
QueueNode* BuyQueueNode(QTDataType data);
// 初始化队列
void QueueInit(Queue* q)
{
	q->front = q->rear = NULL;
}

QueueNode* BuyQueueNode(QTDataType data)
{
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->next = NULL;
	newnode->data = data;
	return newnode;
}

// 队尾入队列 
void QueuePush(Queue* q, QTDataType data)
{
	assert(q);
	QueueNode* newnode = BuyQueueNode(data);
	// 两种情况
	// 1. 队列为空
	if (q->front == NULL)
	{
		q->front = q->rear = newnode;
	}
	else
	{
		q->rear->next = newnode;
		q->rear = q->rear->next;
	}
}

// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	//如果队列只有一个节点
	if (q->front == q->rear)
	{
		q->front = q->front->next;
		free(q->rear);
		q->rear = NULL;
	}
	//如果队列有多个节点
	else
	{
		QueueNode* cur = q->front->next;
		free(q->front);
		q->front = cur;
	}
}

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

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

// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{
	assert(q);
	QueueNode* cur = q->front;
	int count = 0;
	while (cur != q->rear->next)
	{
		count++;
		cur = cur->next;
	}
	return count;
}

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

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

你可能感兴趣的:(蓝桥杯,linq,职场和发展)