主页:醋溜马桶圈-CSDN博客
目录
[1.1 栈的概念及结构](#1.1 栈的概念及结构)
[1.2 栈的实现](#1.2 栈的实现)
[1.2.1 创建栈](#1.2.1 创建栈)
[1.2.2 初始化](#1.2.2 初始化)
[1.2.3 销毁](#1.2.3 销毁)
[1.2.4 入栈](#1.2.4 入栈)
[1.2.5 出栈](#1.2.5 出栈)
[1.2.6 返回栈顶元素](#1.2.6 返回栈顶元素)
[1.2.7 判空](#1.2.7 判空)
[1.2.8 栈的元素个数](#1.2.8 栈的元素个数)
[1.3 实现代码](#1.3 实现代码)
[1.3.1 Stack.h](#1.3.1 Stack.h)
[1.3.2 Stack.c](#1.3.2 Stack.c)
[2.1 队列的概念及结构](#2.1 队列的概念及结构)
[编辑2.2 队列的实现](#编辑2.2 队列的实现)
[2.2.1 创建一个队列](#2.2.1 创建一个队列)
[2.2.2 初始化](#2.2.2 初始化)
[2.2.3 销毁](#2.2.3 销毁)
[2.2.4 入队列](#2.2.4 入队列)
[2.2.5 出队列](#2.2.5 出队列)
[2.2.6 取队列头数据](#2.2.6 取队列头数据)
[2.2.7 取队列尾数据](#2.2.7 取队列尾数据)
[2.2.8 判空](#2.2.8 判空)
[2.2.9 返回队列有效元素个数](#2.2.9 返回队列有效元素个数)
[2.2.10 访问](#2.2.10 访问)
[2.3 实现代码](#2.3 实现代码)
[2.3.1 Queue.h](#2.3.1 Queue.h)
[2.3.2 Queue.c](#2.3.2 Queue.c)
1.数组栈的实现
1.1 栈的概念及结构
栈:一种特殊的线性表 ,其只允许在固定的一端进行插入和删除元素操作
进行数据插入和删除操作的一端称为栈顶,另一端称为栈底
栈中的数据元素遵守后进先出LIFO,(Last In First Out)的原则
- 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶
- 出栈:栈的删除操作叫做出栈,出数据也在栈顶
Stack的Push和Pop遵循后进显先出原则
1.2 栈的实现
栈的实现一般可以使用数组 或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小
1.2.1 创建栈
我们还是用结构体来作为栈的每一个单独的数据块
1.2.2 初始化
这里我们给top赋什么值得认真考虑,需要给0吗?
如果top初始化为0,那么就会出现歧义:top==0是有一个元素还是空
所以,如果top指向栈顶元素 ,需要给top=-1才能区分
如果top指向栈顶元素的下一个位置 ,那么给top初始化为0就可以了
两种方式在初始化的时候会有区别:
- 如果top 指向栈顶元素 ,top=-1:
push:
++top;
a[top]=x;- 如果top 指向栈顶元素的下一个 ,top=0:
push:
a[top]=x;
++top;
我们这里初始化的时候就初始化为0,top就是元素个数:
1.2.3 销毁
1.2.4 入栈
由于top我们初始化为0,这里我们入栈的时候就需要先给值,再++:
1.2.5 出栈
出栈就很简单了:
入栈顺序和出栈顺序是一对多的关系
一种入栈顺序可能会有多种出栈顺序,而一种出栈顺序只对应一种入栈顺序:
1.2.6 返回栈顶元素
1.2.7 判空
或者更简单的写法:
1.2.8 栈的元素个数
1.3 实现代码
1.3.1 Stack.h
cpp
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;//标识栈顶位置
int capacity;
}ST;
//初始化
void STInit(ST* pst);
//销毁
void STDestroy(ST* pst);
//入栈
void STPush(ST* pst, STDataType x);
//出栈
void STPop(ST* pst);
//返回栈顶元素
STDataType STTop(ST* pst);
//判空
bool STEmpty(ST* pst);
//栈的元素个数
int STSize(ST* pst);
1.3.2 Stack.c
cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"
//初始化
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
pst->capacity = 0;
pst->top = 0;
}
//销毁
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->top = pst->capacity = 0;
}
//入栈
void STPush(ST* pst, STDataType x)
{
assert(pst);
if (pst->top == pst->capacity)
{
int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
STDataType* tmp = (STDataType * )realloc(pst->a, sizeof(STDataType) * newcapacity);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->top] = x;
pst->top++;
}
//出栈
void STPop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
pst->top--;
}
//返回栈顶元素
STDataType STTop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
return pst -> a[pst->top - 1];
}
//判空
bool STEmpty(ST* pst)
{
assert(pst);
/*if (pst->top == 0)
{
return true;
}
else
{
return false;
}*/
return pst->top == 0;
}
//栈的元素个数
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
2.队列的实现
2.1 队列的概念及结构
队列:只允许在一端进行插入数据操作 ,在另一端进行删除数据操作 的特殊线性表 ,队列具有先进先出FIFO(First In First Out)
- 入队列:进行插入操作的一端称为队尾
- 出队列:进行删除操作的一端称为队头
2.2 队列的实现
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数 组头上出数据,效率会比较低。
我们可以用单链表来实现:
2.2.1 创建一个队列
先创建一个结构体封装数据之间的关系
再创建一个结构体封装队列的头和尾
2.2.2 初始化
2.2.3 销毁
2.2.4 入队列
2.2.5 出队列
2.2.6 取队列头数据
2.2.7 取队列尾数据
2.2.8 判空
2.2.9 返回队列有效元素个数
2.2.10 访问
当队列不为空的时候,访问队头数据,访问一个pop一个
2.3 实现代码
2.3.1 Queue.h
cpp
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
//创建
typedef int QDataType;
typedef struct QueueNode
{
QDataType val;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* phead;
QNode* ptail;
int size;
}Queue;
//把队列的头尾封装在一个结构体中
//初始化
void QInit(Queue* pq);
//销毁
void QDestroy(Queue* pq);
//入队列
void QPush(Queue* pq, QDataType x);
//出队列
void QPop(Queue* pq);
//取队头数据
QDataType QFront(Queue* pq);
//取队尾数据
QDataType QBack(Queue* pq);
//判空
bool QEmpty(Queue* pq);
//返回队列有效元素个数
int QSize(Queue* pq);
2.3.2 Queue.c
cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
//初始化
void QInit(Queue* pq)
{
assert(pq);
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
//销毁
void QDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->phead;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
//入队列
void QPush(Queue* pq, QDataType x)
{
assert(pq);
//创建newnode
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->val = x;
newnode->next = NULL;
if (pq->ptail == NULL)
{
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
//出队列
void QPop(Queue* pq)
{
assert(pq);
assert(pq->phead);
QNode* del = pq->phead;
pq->phead = pq->phead->next;
free(del);
del = NULL;
if (pq->phead == NULL)
{
pq->ptail = NULL;
//防止ptail成为野指针
}
pq->size--;
}
//取队头数据
QDataType QFront(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->phead->val;
}
//取队尾数据
QDataType QBack(Queue* pq)
{
assert(pq);
assert(pq->ptail);
return pq->ptail->val;
}
//判空
bool QEmpty(Queue* pq)
{
assert(pq);
return pq->phead == NULL;
}
//返回队列有效元素个数
int QSize(Queue* pq)
{
assert(pq);
return pq->size;
}