
༺ 个人主页 · 纪念229 ༻
༺世上本没有路,走的人多了自然就有了༻
这篇文章讲述的是用顺序表实现栈、用单链表实现队列,本文主要讲述栈和队列的定义,希望对大家有所帮助!
文章目录
- 1.Stack.h
- 2.Stack.c
-
- [2.1 STackDesTroy(ST* ps)](#2.1 STackDesTroy(ST* ps))
- [2.2STackPush(ST* ps, STDataType x)](#2.2STackPush(ST* ps, STDataType x))
- [2.3 STackEmpty(ST* ps)](#2.3 STackEmpty(ST* ps))
- [2.4 STackPop(ST* ps)](#2.4 STackPop(ST* ps))
- [2.5 STacksize(ST* ps)](#2.5 STacksize(ST* ps))
- 3.Queue.h
- 4.Queue.c
-
- [4.1QueueInit(Queue* pq)](#4.1QueueInit(Queue* pq))
- [4.3QueuePush(Queue* pq, QDataType x)](#4.3QueuePush(Queue* pq, QDataType x))
- [4.4QueueTmpty(Queue* pq)](#4.4QueueTmpty(Queue* pq))
- [4.5 QueuePop(Queue* pq)](#4.5 QueuePop(Queue* pq))
- [4.6QueueFront(Queue* pq)](#4.6QueueFront(Queue* pq))
- [4.7 QueueBack(Queue* pq)](#4.7 QueueBack(Queue* pq))
- [4.8QueueSize(Queue* pq)](#4.8QueueSize(Queue* pq))
1.Stack.h
栈的头文件,讲述程序的功能
代码展示
点我展开
c
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//定义栈的结构
typedef int STDataType;
typedef struct Stack
{
STDataType* arr;
int top;
int capacity;
}ST;
//初始化
void STackInit(ST* ps);
//销毁
void STackDesTroy(ST* ps);
//入栈---栈顶
void STackPush(ST* ps,STDataType x);
//出栈---栈顶
void STackPop(ST* ps);
//取栈顶元素
STDataType STackTop(ST* ps);
//获取栈中有效元素个数
int STacksize(ST* ps);
//栈是否为空
bool STackEmpty(ST* ps);
2.Stack.c
说一下有些函数没有断言,主要讲述重要的地方
2.1 STackDesTroy(ST* ps)
功能:把栈清空
代码展示
c
//销毁
void STackDesTroy(ST* ps)
{
if(ps->arr)
free(ps->arr);
ps->arr =NULL;
ps->capacity = ps->top = 0;
}
我们需要判断栈里是否为空,才能free里的内容
2.2STackPush(ST* ps, STDataType x)
功能:入栈
代码展示
c
//入栈---栈顶
void STackPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->capacity == ps->top)
{
//增容
int newcapacity = ps->arr == NULL ? 4 : 2 * ps->capacity;
//扩容用realloc,用malloc前面的会消失
STDataType* tmp = (STDataType*)realloc(ps->arr,sizeof(STDataType)* newcapacity);
if (tmp == NULL) {
perror("malloc fial");
exit(1);
}
ps->arr = tmp;
ps->capacity =newcapacity;
}
ps->arr[ps->top++] = x;
}
增容:判断栈是否为空,为空返回4字节否则返回2倍原字节
扩容用realloc不用malloc
原因:malloc是重新启用空间会把原来栈的数据清空
然后给栈赋值,记得更新栈顶和容量
2.3 STackEmpty(ST* ps)
功能:判断栈是否为空
代码展示
c
bool STackEmpty(ST* ps)
{
assert(ps);
//用top判断栈是否为空
return ps->top == 0;
}
要判断一个东西建议用bool类型的函数
判断栈为空就是判断栈顶top是否为0
2.4 STackPop(ST* ps)
功能:出栈
c
//出栈---栈顶
void STackPop(ST* ps)
{
//判断栈是否为空
assert(!STackEmpty(ps));
--ps->top;
}
要出栈要判断栈是否为空
出栈实际上是给栈顶减减
## 2.5 STackTop(ST* ps)
功能:得到栈顶的元素
```c
//取栈顶元素
STDataType STackTop(ST* ps)
{
//判断栈是否为空
assert(!STackEmpty(ps));
//取的是ps->arr[ps->top - 1](栈顶的元素)而不是栈顶数
return ps->arr[ps->top - 1];
}
既然要取栈顶元素就要判断栈是否为空
直接返回栈顶元素即可(返回的下标是top - 1)
2.5 STacksize(ST* ps)
功能:获取栈中存储的有效个数
代码展示
c
//获取栈中有效元素个数
int STacksize(ST* ps)
{
assert(ps);
return ps->top;
}
栈中的有效个数就是栈顶的值
3.Queue.h
展示函数功能
代码展示
点我展开
c
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int QDataType;
//队列节点的结构
typedef struct queueNode
{
QDataType val;
struct queueNode* next;
//
}QueueNode;
//队列的结构
typedef struct queue
{
QueueNode* phead;
QueueNode* ptail;
//int size;//队列中有效数据的个数
}Queue;
//初始化
void QueueInit(Queue* pq);
//销毁队列
void QueueDesTroy(Queue* pq);
//入队------队尾
void QueuePush(Queue* pq, QDataType x);
//出队------队头
void QueuePop(Queue* pq);
//队列判空
bool QueueTmpty(Queue* pq);
//队列有效元素个数
int QueueSize(Queue* pq);
//取队头数据
QDataType QueueFront(Queue* pq);
//取队尾数据
QDataType QueueBack(Queue* pq);
>队列是由两个指针组成的结构体,包括头phead和尾ptail >队列里是单链表组成的 ```
4.Queue.c
实现队列功能
4.1QueueInit(Queue* pq)
功能:初始化队列
代码展示
c
//初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = pq->ptail = NULL;
}
把头尾指针置空
## 4.2QueueDesTroy(Queue* pq)
功能:销毁队列里的数据
代码展示
```c
//销毁队列
void QueueDesTroy(Queue* pq)
{
assert(pq);
QueueNode* pcur = pq->phead;
while (pcur)
{
QueueNode* next = pcur->next;
free(pcur);
pcur = next;
}
pq->phead = pq->ptail = NULL;
}
给个next保存下一位的地址完成节点的销毁
最后给头指针和尾指针置空
4.3QueuePush(Queue* pq, QDataType x)
功能:入队(尾入队)
代码展示
c
//入队------队尾
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
if (newnode == NULL)
{
perror("malloc fial");
exit(1);
}
newnode->val = x;
newnode->next = NULL;
//队列为空
if (pq->phead == NULL) {
pq->phead = pq->ptail = newnode;
}
else {
pq->ptail->next = newnode;
pq->ptail = newnode;
}
//ps->size++;
}
每次入队都创建一个节点把val赋好next指向NULL
如果队列为空就把头指针(phead)和尾指针(ptail)被赋值为newnode指针,若不是就把尾指针指向newnode再把ptail赋值为newnode指针
4.4QueueTmpty(Queue* pq)
功能:判断队列是否为空
代码展示
c
//队列判空
bool QueueTmpty(Queue* pq)
{
assert(pq);
return pq->phead == NULL;
}
判断队列为空就是看头指针是否等于NULL
4.5 QueuePop(Queue* pq)
功能:出队(头指针chu队列)
代码展示
c
//出队------队头
void QueuePop(Queue* pq)
{
assert(!QueueTmpty(pq));
//只有一个节点,phead-ptai都置为空
if (pq->phead == pq->ptail)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else {
QueueNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
//pq->size--;
}
要出队列先判断队列是否为空
如果只有一个节点就free头结点后置空
不是则给个next指针(找到新的头结点)然后free(phead),把phead赋值为next
4.6QueueFront(Queue* pq)
功能:获取队头信息
代码展示
c
//取对头数据
QDataType QueueFront(Queue* pq)
{
//队列判空
assert(!QueueTmpty(pq));
return pq->phead->val;
}
判断队列是否为空,然后返回对头数据
4.7 QueueBack(Queue* pq)
功能:获取队尾信息
代码展示
c
//取队尾数据
QDataType QueueBack(Queue* pq)
{
//队列判空
assert(!QueueTmpty(pq));
return pq->ptail->val;
}
判断队列是否为空,返回队尾数据
4.8QueueSize(Queue* pq)
功能:获取队列有多少有效数据
方案1.
把队列多加int size,当出队入队是加加减减(前面代码有注释)
具体代码在方案2中也有注释
方案2.
遍历队列返回有效个数
代码展示
c
//队列有效元素个数
int QueueSize(Queue* pq)
{
assert(pq);
//第一种方案遍历链表------适用于不会频繁调用队列有效个数的场景
QueueNode* pcur = pq->phead;
int size = 0;
while (pcur)
{
++size;
pcur = pcur->next;
}
return size;
//第二种方式:遍历链表------适用于频繁调用有效数据的场景
//return pq->size;
}
方案1适用于不常调用有效个数的情况
方案2适用于常调用有效个数的情况
这篇文章在这里就结束了,希望对你有所帮助!