当前位置: 首页 > news >正文

【数据结构】栈与队列

本文是小编巩固自身而作,如有错误,欢迎指出!

1.栈

1.1 概念与结构

栈:⼀种特殊的线性表,其只允许在固定的⼀端进⾏插⼊和删除元素操作。进⾏数据插⼊和删除操作的⼀端称为栈顶,另⼀端称为栈底。栈中的数据元素遵守后进先出的原则。

栈的实现⼀般可以使⽤数组或者链表实现,相对⽽⾔数组的结构实现更优⼀些。因为数组在尾上插⼊ 数据的代价⽐较⼩。(在之前我们学过,数组的尾插时间复杂度是O(1),而链表的复杂度是O(N))

1.2栈的实现

1.2.1栈的结构


//定义栈的结构
typedef int stdatatype;
struct Stack
{stdatatype* arr;int top;//指向栈顶int capacity;//栈的容量
};
typedef struct Stack ST;

这里的栈我们采用类似于顺序表的方式实现,一个栈包含如上码所示的三个内容。

1.2.2栈的初始化

和顺序表类似,将数组置空,数据置零。

void stackinit(ST* ps)//栈初始化
{ps->arr = NULL;ps->top = ps->capacity = 0;
}

 1.2.3入栈

void stackpush(ST* ps, stdatatype x)//入栈
{if (ps->top == ps->capacity)//栈满了{//增容int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;stdatatype* tmp = (stdatatype*)realloc(ps->arr, newcapacity*sizeof(stdatatype));if (tmp == NULL){perror("realloc fail");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}//栈未满ps->arr[ps->top++] = x;
}

 1.2.4出栈

void stackpop(ST* ps)//出栈
{assert(!stackempty(ps));//判空--ps->top;
}

在出栈时需要考虑是否为空的情况我们这里使用bool函数。

bool stackempty(ST* ps)
{assert(ps);return ps->top == 0;
}

 1.2.5取栈顶元素

stdatatype stacktop(ST* ps)//取栈顶元素
{assert(!stackempty(ps));return ps->arr[ps->top - 1];
}

1.2.6销毁栈 

void stackdestroy(ST* ps)//销毁栈
{if (ps->arr){free(ps->arr);ps->arr = NULL;ps->top = ps->capacity = 0;}
}	  

1.3完整代码实现

.h文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>//定义栈的结构
typedef int stdatatype;
struct Stack
{stdatatype* arr;int top;//指向栈顶int capacity;//栈的容量
};
typedef struct Stack ST;void stackinit(ST* ps);//栈初始化
void stackpush(ST* ps, stdatatype x);//入栈
void stackpop(ST* ps);//出栈
bool stackempty(ST* ps);//判空
stdatatype stacktop(ST* ps);//取栈顶元素
void stackdestroy(ST* ps);//销毁栈

.c文件 

#define _CRT_SECURE_NO_WARNINGS
#include"stack.h"void stackinit(ST* ps)//栈初始化
{ps->arr = NULL;ps->top = ps->capacity = 0;
}
void stackpush(ST* ps, stdatatype x)//入栈
{if (ps->top == ps->capacity){//增容int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;stdatatype* tmp = (stdatatype*)realloc(ps->arr, newcapacity*sizeof(stdatatype));if (tmp == NULL){perror("realloc fail");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}ps->arr[ps->top++] = x;
}
bool stackempty(ST* ps)
{assert(ps);return ps->top == 0;
}
void stackpop(ST* ps)//出栈
{assert(!stackempty(ps));//判空--ps->top;
}
stdatatype stacktop(ST* ps)//取栈顶元素
{assert(!stackempty(ps));return ps->arr[ps->top - 1];
}
void stackdestroy(ST* ps)//销毁栈
{if (ps->arr){free(ps->arr);ps->arr = NULL;ps->top = ps->capacity = 0;}
}	  

.c文件(测试) 

#define _CRT_SECURE_NO_WARNINGS
#include"stack.h"
void test01()
{ST st;stackinit(&st);stackpush(&st, 1);stackpush(&st, 2);stackpush(&st, 3);stackpush(&st, 4);stackpop(&st);while (!stackempty(&st)){int top = stacktop(&st);printf("%d ", top);stackpop(&st);}
}
int main()
{test01();return 0;
}

2.队列 

2.1概念与结构

概念:只允许在⼀端进⾏插⼊数据操作,在另⼀端进⾏删除数据操作的特殊线性表,队列具有先进先出。

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

2.2队列的实现

2.2.1队列的结构

typedef int QDdatatype;
//节点结构
typedef struct QueueNode
{QDdatatype data;struct QueueNode* next;
}QUnode;
//队列结构
typedef struct Queue
{struct QueueNode* phead;struct QueueNode* ptail;//int size;//有效数据的个数
}QU;

为了避免像一般单链表在尾部进行操作导致时间复杂度增加,我们相较于单链表多创建一个尾节点 。

2.2.2队列的初始化

void QUinit(QU* pq)//初始化
{assert(pq);pq->phead = pq->ptail = NULL;//pq->size = 0;
}

2.2.3入队--队尾

void QUpushi(QU* pq, QDdatatype x)//入队--队尾
{assert(pq);//队列为空QUnode* newnode = (QUnode*)malloc(sizeof(QUnode));if (newnode == NULL){perror("malloc fail");exit(1);}newnode->data = x;newnode->next = NULL;if (pq->phead == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = pq->ptail->next;}//pq->size++;
}

类似于链表中尾插。

2.2.4出队--队头

void QUpop(QU * pq)//出队--队头{assert(!QUempty(pq));//只有一个节点if (pq->phead == pq->ptail){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QUnode* next = pq->phead->next;free(pq->phead);pq->phead = next;}/*pq->size--;*/}

在出队时就要考虑队列为空的情况

bool QUempty(QU* pq)//队列判空
{assert(pq);return pq->phead == NULL;
}

2.2.5 取头、尾数据

QDdatatype QUfront(QU* pq)//取头数据{assert(!QUempty(pq));return pq->phead->data;}QDdatatype QUback(QU* pq)//取尾数据{assert(!QUempty(pq));return pq->ptail->data;}

2.2.6销毁队列 

void QUdestroy(QU* pq)//销毁队列{assert(pq);QUnode* pcur = pq->phead;while (pcur){QUnode* next = pq->phead;free(pcur);pcur = next;}pq->phead = pq->ptail = NULL;/*pq->size = 0;*/}

 2.3完整代码实现

.h文件

#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>
typedef int QDdatatype;
//节点结构
typedef struct QueueNode
{QDdatatype data;struct QueueNode* next;
}QUnode;
//队列结构
typedef struct Queue
{struct QueueNode* phead;struct QueueNode* ptail;//int size;//有效数据的个数
}QU;
void QUinit(QU* pq);//初始化
void QUpushi(QU* pq, QDdatatype x);//入队--队尾
void QUpop(QU* pq);//出队--队头
bool QUempty(QU* pq);//队列判空
QDdatatype QUfront(QU* pq);//取头数据
QDdatatype QUback(QU* pq);//取尾数据
void QUdestroy(QU* pq);//销毁队列
int QUsize(QU* pq);//队列的有效元素

.c文件

#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"
void QUinit(QU* pq)//初始化
{assert(pq);pq->phead = pq->ptail = NULL;//pq->size = 0;
}
bool QUempty(QU* pq)//队列判空
{assert(pq);return pq->phead == NULL;
}
void QUpushi(QU* pq, QDdatatype x)//入队--队尾
{assert(pq);//队列为空QUnode* newnode = (QUnode*)malloc(sizeof(QUnode));if (newnode == NULL){perror("malloc fail");exit(1);}newnode->data = x;newnode->next = NULL;if (pq->phead == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = pq->ptail->next;}//pq->size++;
}void QUpop(QU * pq)//出队--队头{assert(!QUempty(pq));//只有一个节点if (pq->phead == pq->ptail){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QUnode* next = pq->phead->next;free(pq->phead);pq->phead = next;}/*pq->size--;*/}QDdatatype QUfront(QU* pq)//取头数据{assert(!QUempty(pq));return pq->phead->data;}QDdatatype QUback(QU* pq)//取尾数据{assert(!QUempty(pq));return pq->ptail->data;}void QUdestroy(QU* pq)//销毁队列{assert(pq);QUnode* pcur = pq->phead;while (pcur){QUnode* next = pq->phead;free(pcur);pcur = next;}pq->phead = pq->ptail = NULL;/*pq->size = 0;*/}int QUsize(QU* pq)//队列的有效元素{/*assert(pq);QUnode* pcur = pq->phead;int size = 0;while (pcur){size++;pcur = pcur->next;}*//*return pq->size;*/}

.c文件(测试) 

#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"void test01()
{QU q;QUinit(&q);QUpushi(&q, 1);QUpushi(&q, 2);QUpushi(&q, 3);		QUpop(&q);int front = QUfront(&q);int back = QUback(&q);printf("%d\n", front);printf("%d\n", back);void QUdestroy(QU * pq);//销毁队列}
int main()
{test01();return 0;
}

 在具体实现思路都与之前的顺序表与链表相似,有不理解的可以看看前篇

顺序表

单链表

本次分享就到这里结束了,感谢阅读!

相关文章:

  • ExecutorService详解:Java 17线程池管理从零到一
  • nestjs[一文学懂TypeORM在nestjs中的日常使用]
  • C++核心编程--3 函数提高
  • 小白学编程之——数据库如何性能优化
  • 【RAP】RAP动作与流行舞蹈/街舞
  • unity terrain 在生成草,树,石头等地形障碍的时候,无法触发碰撞导致人物穿过模型
  • 图深度学习、EMD和VMD详解
  • 【日撸 Java 三百行】Day 16(递归)
  • 数据结构之图的应用场景及其代码
  • 修复“ImportError: DLL load failed while importing lib: 找不到指定的程序”笔记
  • Cocos Creator 3.8.5 构建依赖环境配置文档
  • 分页管理调试
  • 讯联云库项目开发技术栈总结(一)
  • 如何实现k8s高可用
  • 通义千问-langchain使用构建(二)
  • 5.15本日总结
  • 非常详细的HTTP状态码介绍
  • 验证可行分享-Rancher部署文档
  • 【Linux】gcc从源码编译安装,修改源码,验证修改的源码
  • Linux文件操作系统接口介绍,以及文件描述符的本质
  • 习近平就乌拉圭前总统穆希卡逝世向乌拉圭总统奥尔西致唁电
  • 【社论】城市更新,始终以人为核心
  • 新城悦服务:独董许新民辞任,新任独董与另两人组成调查委员会将调查与关联方资金往来
  • 警方通报男子广州南站持刀伤人:造成1人受伤,嫌疑人被控制
  • 伊朗最高领袖顾问:伊朗愿承诺永不制造核武,换取美解除制裁
  • 光明日报:家长孩子共同“息屏”,也要保证高质量陪伴