前言
为什么会定义栈和队列这两种数据结构呢?
原因在于:
之所以会定义栈和队列这样的数据结构
是因为他们有两大特性:
第一: 他们可以保存程序运行路径中各个点的信息,以便用于回溯操作或其他需要访问已经访问过的节点信息的操作。
比如: 栈用于解决迷宫问题,就是用到了若线路不通,需要回溯到已访问过的结点,从那个结点再做一次与这次路径不同的选择。
第二: 先进后出 和 先进先出的 次序
先进后出次序 其实就是一种将序列反序操作的次序
先进先出次序 其实就是一种将序列顺序操作的次序
比如: 利用栈的先进后出可以解决进制转化问题 ,即:先将个位余数进栈,再将十位余数进栈,然后百位,千位 等 ,这样出栈的时候顺序就成了反序出栈,即:先千位,百位,然后十位,最后个位。
目录
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) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头
文章来源:https://www.toymoban.com/news/detail-410739.html
2.2队列的实现
文章来源地址https://www.toymoban.com/news/detail-410739.html
// 链式结构:表示队列
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;
}
到了这里,关于C语言数据结构——线性表之栈和队列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!