C语言数据结构——线性表之栈和队列

前言

为什么会定义栈和队列这两种数据结构呢?
原因在于:
之所以会定义栈和队列这样的数据结构
是因为他们有两大特性
第一: 他们可以保存程序运行路径中各个点的信息,以便用于回溯操作或其他需要访问已经访问过的节点信息的操作。
比如: 栈用于解决迷宫问题,就是用到了若线路不通,需要回溯到已访问过的结点,从那个结点再做一次与这次路径不同的选择。
第二: 先进后出 和 先进先出的 次序
先进后出次序 其实就是一种将序列反序操作的次序
先进先出次序 其实就是一种将序列顺序操作的次序
比如: 利用栈的先进后出可以解决进制转化问题 ,即:先将个位余数进栈,再将十位余数进栈,然后百位,千位 等 ,这样出栈的时候顺序就成了反序出栈,即:先千位,百位,然后十位,最后个位。

目录

1.栈的表示和实现
2.队列的表示和实现

1.栈的表示和实现

1.1栈的概念和基本结构

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

在这里插入图片描述
在这里插入图片描述

1.2栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。
在这里插入图片描述
链栈的进出示意图
在这里插入图片描述

// 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
typedef int STDataType;
#define N 10
typedef struct Stack
{
    
    
STDataType arr[N];
int top; // 栈顶
}Stack;
// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
    
    
STDataType* arr;
int top; // 栈顶
int capacity;  // 容量
}Stack;
// 初始化栈
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);

1.2.1初始化栈

//初始化
void StackInit(stack* ps)
{
    
    
	assert(ps);
	ps->arr = (STDataType*)malloc(4 * sizeof(STDataType));
	 if (ps->arr == NULL)
	 {
    
    
		 printf("malloc fail\n");
		 exit(-1);
	 }
	ps->capacity = 4;
	ps->top = 0;

}

1.2.2 入栈/压栈

//压栈
void StackPush(stack* ps, STDataType x)
{
    
    
	assert(ps);
	if (ps->top == ps->capacity)
	{
    
    
		STDataType* temp= (STDataType*)realloc(ps->arr, ps->capacity *2* sizeof(STDataType));
		if (temp == NULL)
		{
    
    
			printf("realloc fail\n");
			exit(-1);
		}
		else
		{
    
    
			ps->arr = temp;
			ps->capacity *= 2;
		}
	}
	ps->arr[ps->top] = x;
	ps->top++;
}

1.2.3出栈

//出栈
void StackPop(stack* ps)
{
    
    
	assert(ps);
	assert(ps->top > 0);
	ps->top--;

}

1.2.4获取栈顶元素

//返回栈顶元素
STDataType StackTop(stack* ps)
{
    
    
	assert(ps);
	assert(ps->top > 0);
	return (ps->arr[ps->top - 1]);
}

1.2.5获取栈中有效个数

//返回栈顶元素
STDataType StackTop(stack* ps)
{
    
    
	assert(ps);
	assert(ps->top > 0);
	return (ps->arr[ps->top - 1]);
}

1.2.6 返回栈中有效元素个数

//栈长
int StackSize(stack* ps)
{
    
    
	assert(ps);

	return ps->top;
}

1.2.7 判空

//判空
bool StackEmpty(stack* ps)
{
    
    
	assert(ps);
	return ps->top == 0;
}

1.2.8 销毁栈

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

2 队列的表示和实现

2.1队列的概念及结构

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

2.2队列的实现

在这里插入图片描述

// 链式结构:表示队列
typedef struct QListNode
{
    
    
struct QListNode* next;
QDataType data;
}QNode;
// 队列的结构
typedef struct Queue
{
    
    
QNode* head;
QNode* tail;
}Queue;
// 初始化队列
void QueueInit(Queue* pq);
// 队尾入队列
void QueuePush(Queue* pq, QDataType data);
// 队头出队列
void QueuePop(Queue* pq);
// 获取队列头部元素
QDataType QueueFront(Queue* pq);
// 获取队列队尾元素
QDataType QueueBack(Queue* pq);
// 获取队列中有效元素个数
int QueueSize(Queue* pq);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* pq);
// 销毁队列
void QueueDestroy(Queue* pq);

2.2.1初始化队列

//初始化
void QueueInit(Queue* pq)
{
    
    
	assert(pq);
	pq->head = NULL;
	pq->tail = NULL;
}

2.2.2 队尾入队列

//队尾入
void QueuePush(Queue* pq, QDataType x)
{
    
    
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
    
    
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->tail == NULL)
	{
    
    
		pq->tail = newnode;
		pq->head = newnode;
	}
	else
	{
    
    
		pq->tail->next = newnode;
		pq->tail = newnode;


	}

}

2.2.3 队头出队列

//队头出
void QueuePop(Queue* pq)
{
    
    
	//1.一个
	//2.多个
	assert(pq);
	assert(pq->head);
	if (pq->head->next == NULL)
	{
    
    
		free(pq->head);
		pq->head = pq->tail = NULL;

	}
	else
	{
    
    
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
}

2.2.4 获取队列头部元素

//取队列的队头元素
QDataType QueueFront(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->head);
	return pq->head->data;
}

2.2.5 获取队列队尾元素

//取队列的队尾元素
QDataType QueueBack(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->head);
	return pq->tail->data;
}

2.2.6 获取队列有效元素个数

//返回队列长度
int QueueSize(Queue* pq)
{
    
    
	assert(pq);
	int size = 0;
	QNode* cur = pq->head;
	while (!cur)
	{
    
    
		size++;
		cur = cur->next;
	}
	return size;
}

2.2.7 判空

//判空
bool QueueEmpty(Queue* pq)
{
    
    
	assert(pq);
	return pq->head == NULL;
}

2.2.8 销毁队列

//销毁队列
void QueueDestroy(Queue* pq)
{
    
    
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
    
    
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;

}

猜你喜欢

转载自blog.csdn.net/weixin_63181097/article/details/130020705