欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > 数据结构 | 第四章 | 栈和队列

数据结构 | 第四章 | 栈和队列

2024/11/8 14:32:14 来源:https://blog.csdn.net/ZJC744575/article/details/143599321  浏览:    关键词:数据结构 | 第四章 | 栈和队列

线性表之栈和队列

1.栈的表示和实现

1.1栈的概念及结构

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

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

出栈:栈的删除操作叫做出栈。出数据也在栈顶

image-20241103212738848

1.2栈的实现

  • 分析下用链表还是数组实现好?
  • :都可以

image-20241103232722355

image-20241103232756279

image-20241103232942252

栈顶top给1与-1

image-20241105162002385

代码实现

Stack.h头文件:

// Created by zjc on 2024/11/3 21:47#pragma once#include "stdio.h"
#include "stdbool.h"
#include "stdlib.h"
#include "assert.h"typedef int STDataType;typedef struct Stack{// 一般使用动态,不使用静态STDataType * a;// 表示栈顶int top;int capacity;
}ST;// 0.初始化
void StackInit(ST * ps);// 0.销毁
void StackDestory(ST * ps);// 栈一定是在栈顶操作
// 1.入栈
void StackPush(ST * ps,STDataType x);// 删除栈顶元素
// 2.出栈
void StackPop(ST * ps);// 3.取栈顶数据
STDataType StackTop(ST * ps);// 4.求数据个数
int StackSize(ST * ps);// 5.判断是否为空,bool判断真假
bool StackEmpty(ST * ps);

Stack.c接口设置:

  • 初始化
#include "Stack.h"// 0.初始化
void StackInit(ST * ps){// 正常结构体的地址给我,是不能为空的assert(ps);// 开辟空间:先开辟4个intps->a = (STDataType*)malloc(sizeof(STDataType)*4);if(ps->a == NULL){ // 表示未分配成功printf("malloc fail\n");exit(-1);}// 容量,可以存4个数据ps->capacity =4;// 栈顶开始为0,指向的是栈顶元素的下一个ps->top = 0;
}
  • 销毁
// 0.销毁
void StackDestory(ST * ps){// 正常结构体的地址给我,是不能为空的assert(ps);// 释放psfree(ps->a);ps->a = NULL;// 同时将容量和栈顶置为0ps->top = ps->capacity = 0;
}
  • 入栈

image-20241105162125806

// 1.入栈
void StackPush(ST * ps,STDataType x){assert(ps);// 容量满了就需要扩容if(ps->top == ps->capacity){// 直接扩容2倍STDataType * tmp = (STDataType*)realloc(ps->a,ps->capacity*2*sizeof(STDataType));// 如果扩容失败if(tmp == NULL){printf("realloc fail\n");// 终止程序exit(-1);}else{// 分配成功,赋值给ps->aps->a = tmp;// 容量变成原来2倍ps->capacity *= 2;}}// 插入一个元素,然后栈顶++ps->a[ps->top] = x;ps->top++;/** 如果之前top在栈顶,就要先++在放数据*/
}
  • 出栈

image-20241105162342650

// 2.出栈
void StackPop(ST * ps){assert(ps);// 栈空了,调用pop,直接终止程序报错assert(ps->top > 0);// 直接减减ps->top--;
}
  • 取栈顶数据
// 3.取栈顶数据
STDataType StackTop(ST * ps){assert(ps);// 栈空了,调用pop,直接中止程序报错assert(ps->top > 0);return ps->a[ps->top-1];
}
  • 求数据个数
// 4.求数据个数
int StackSize(ST * ps){assert(ps);return ps->top;
}
  • 判断是否为空
// 5.判断是否为空,bool判断真假
bool StackEmpty(ST * ps){assert(ps);// 等于0则为真,为空;不等于0则为假不为空return ps->top == 0;
}

Test.h测试文件

// Created by zjc on 2024/11/3 21:47
#include "Stack.h"int main() {ST st;// 初始化// 注意需要传指针(地址),结构体是值传递StackInit(&st);StackPush(&st,1);StackPush(&st,2);StackPush(&st,3);// 入栈3个在出栈2个StackPop(&st);StackPop(&st);StackPush(&st,4);StackPush(&st,5);// 在入2个StackPush(&st,1);StackPush(&st,2);// 如果不为NULL就去取栈顶的数据while(!StackEmpty(&st)){printf(" %d", StackTop(&st));// 栈是不能随便遍历的// 取栈顶元素后出栈StackPop(&st);}printf("\n");// 销毁StackDestory(&st);return 0;
}

2.队列的表示和实现

2.1队列的概念及结构

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

入队列:进行插入操作的一端称为队尾

出队列:进行删除操作的一端称为队头

image-20241105163951195

2.2队列的实现

实现方式:链表

image-20241106220411535

头文件Queue.h

// Created by zjc on 2024/11/5 16:31#pragma once#include "stdio.h"
#include "stdbool.h"
#include "stdlib.h"
#include "assert.h"typedef int QDataType;// 链式结构:表示队列
typedef struct QueueNode {struct QueueNode *next;QDataType data;
} QNode;// 队列结构:队头指针和队尾指针结构体
typedef struct Queue {QNode *head;QNode *tail;
} Queue;// 0.初始化
void QueueInit(Queue *pq);// 0.销毁
void QueueDestory(Queue *pq);// 1、队尾入
void QueuePush(Queue *pq, QDataType x);// 2.队头出
void QueuePop(Queue *pq);// 3.取队头数据
QDataType QueueFront(Queue *pq);// 4.取队尾数据
QDataType QueueBack(Queue *pq);// 5.取数据的个数
int QueueSize(Queue *pq);// 6.判断是否为空
bool QueueEmpty(Queue *pq);

Queue.c文件

#include "Queue.h"// 0.初始化
void QueueInit(Queue *pq) {assert(pq);// 最开始将队首指针和队尾指针初始化为空pq->head = pq->tail = NULL;
}

1.队尾入

image-20241106221718420

// 1.队尾入
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->head = pq->tail = newnode;} else {// 不是空,有节点就连接到节点的后面pq->tail->next = newnode;// 将tail移动到最后pq->tail = newnode;}
}

2.队头出

image-20241106222101056

image-20241106222122178

// 2.队头出
void QueuePop(Queue *pq) {assert(pq);// 判断队列是不等于空的assert(pq->head);// 分为一个节点和多个节点//  这里表示就只有一个节点了,释放掉后将tail和head都置为空// 防止野指针tailif (pq->head->next == NULL) {free(pq->head);pq->head = pq->tail = NULL;} else {// 保留head的下一个QNode *next = pq->head->next;free(pq->head);pq->head = next;}
}

3.判断空

// 3.判断是否为空:等于空则返回true否则false
bool QueueEmpty(Queue *pq) {assert(pq);return pq->head == NULL;
}

4.取队头数据

// 4.取队头数据
QDataType QueueFront(Queue *pq) {assert(pq);// 可以最后添加判断头是否为空,尾空则不调用assert(pq->head);// 直接返回头中的数据return pq->head->data;
}

5.取队尾数据

//  5.取队尾数据
QDataType QueueBack(Queue *pq) {assert(pq);assert(pq->head);return pq->tail->data;
}

6.取数据的个数

// 6.取数据的个数
int QueueSize(Queue *pq) {assert(pq);int size = 0;QNode *cur = pq->head;while (cur) {++size;cur = cur->next;}return size;
}

7.销毁

// 7.销毁
void QueueDestory(Queue *pq) {assert(pq);QNode *cur = pq->head;while (cur) {// 将下一个存储起来QNode *next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;
}

Test.c文件

// Created by zjc on 2024/11/5 16:32
#include "Queue.h"void TestQueue(){Queue q;QueueInit(&q);QueuePush(&q,1);QueuePush(&q,2);// 出队列之前printf(" %d\n", QueueFront(&q));// 中途出一个QueuePop(&q);// 出队列之后printf(" %d\n", QueueFront(&q));QueuePush(&q,3);QueuePush(&q,4);while(!QueueEmpty(&q)){// 取队头数据,然后删除队头printf(" %d", QueueFront(&q));// 队头出,也是需要边删边出QueuePop(&q);}//    printf("%d", QueueFront(&q));QueueDestory(&q);
}int main(){TestQueue();return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com