一、栈
1、定义
1、栈(Stack)是限定仅在表尾(栈顶)进行插入和删除的线性表,特点:后进先出
2、栈有顺序存储结构也有链式存储结构;
顺序存储结构:利用一组地址连续的存储单元依次存放栈底到栈顶的数据元素,可用top=0/-1表示栈内元素个数情况,下面将展示top=0表示栈为空进行的一系列初始操作
栈的顺序存储表示
typedef int STDataType;
//栈的实现可以用顺序栈(数组)也可以用链栈(栈顶为首元结点),数组较为方便
// 以下为顺序栈的实现
//typedef struct Stack//静态(大小固定)
//{
// STDataType a[N];
// int size;
//};
typedef struct
{
STDataType* a;//栈元素的首地址
int top;//栈顶指针
int capacity;//栈所占空间
}Stack;
栈的基本操作函数
头文件(文件名Stack.h)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
#include<stdlib.h>
#define N 100
#define Increment 10//每次扩容时的增量
typedef int STDataType;//将int换个名字
//接口函数的声明
void InitStack(Stack* pst);//初始化栈
void DestoryStack(Stack* pst);//销毁栈
void StackPush(Stack* pst,STDataType x);//入栈
STDataType StackPop(Stack* pst);//出栈
int StackSize(Stack* pst);//获取栈元素的个数
int StackEmpty(Stack* pst);//判断栈是否为空
STDataType GetTop(Stack* pst);//获取栈顶的数据
接口函数的实现
#include "Stack.h"
void InitStack(Stack* pst)//初始化栈
{
assert(pst);//断言,防止不慎传入的结构体指针为空
pst->a = (STDataType*)malloc(sizeof(STDataType) * 100);//先给栈分配一个空间,首地址为pst->a
pst->top = 0;
pst->capacity = 100;
}
void DestoryStack(Stack* pst)//销毁栈
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->top = 0;
pst->capacity = 0;
}
void StackPush(Stack* pst,STDataType x)//入栈
{//Increment扩容增量
assert(pst);
if (pst->capacity == pst->top)//空间满了扩容
{
pst->a = (STDataType*)realloc(pst->a, (pst->capacity + Increment) * sizeof(STDataType));
if (!pst->a)exit(-1);
pst->capacity = pst->capacity + Increment;
}
pst->a[pst->top] = x;
pst->top++;
}
STDataType StackPop(Stack* pst)//出栈
{//返回出栈的栈顶元素
assert(pst);
assert(pst->top > 0);
return pst->a[--pst->top];
// pst->top--;
}
int StackSize(Stack* pst)//获取栈元素的个数
{
assert(pst);
return pst->top;
}
int StackEmpty(Stack* pst)//判断栈是否为空
{
assert(pst);
if (pst->top == 0)return 1;
else return 0;
}
STDataType GetTop(Stack* pst)//获取栈顶的数据
{
assert(pst);
assert(pst->top > 0);
return pst->a[pst->top - 1];
3.实践部分与运行截图
#define _CRT_SECURE_NO_WARNINGS
#include "Stack.h"
void TestStack1()
{
Stack s1;
InitStack(&s1);//初始化
StackPush(&s1, 1);//入栈四个元素1234
StackPush(&s1, 2);
StackPush(&s1, 3);
StackPush(&s1, 4);
while (!StackEmpty(&s1))//从栈顶4开始逐个打印
{
printf("%d ", GetTop(&s1));//获取栈顶元素
StackPop(&s1);//出栈一个
}
printf("\n");
StackPush(&s1, 5);
int x=0;
x=StackPop(&s1);//将出栈的栈顶元素赋值给x
printf("%d\n", x);
}
int main()
{
TestStack1();
return 0;
}
栈的链式存储表示
根据栈后进先出的特点,因此进行操作时采用头插和头删,和单链表相似。
二、队列
1、定义
只允许在表的一端插入和另一端删除,特点:先进先出,类似于排队打饭,先排队的先打饭。
2、队列的链式存储结构
1、头文件
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int QDataType;
typedef struct QueueNode
{
QDataType data;
struct QNode* next;
}QueueNode;
typedef struct Queue
{
QueueNode* head;//头指针用来指向队头
QueueNode* tail;//尾指针用来指向队尾
}Queue;
void QueueInit(Queue* pq);//初始化队列
void QueueDestory(Queue* pq);//销毁队列
void QueuePush(Queue* pq,QDataType x);//进队列
void QueuePop(Queue* pq);//出队列
QDataType QueueFront(Queue* pq);//取队头数据
QDataType QueueBack(Queue* pq);//取队尾数据
int QueueEmpty(Queue* pq);//判断队列是否为空
int QueueSize(Queue* pq);//求队列元素个数
2、基本函数实现
#include "Queue.h"
void QueueInit(Queue* pq)//初始化队列
{//pq为结构体指针,是结构体的地址,队头队尾指针存放在结构体中因此不用传二级指针
pq->head = NULL;
pq->tail = NULL;
}
void QueueDestory(Queue* pq)//销毁队列
{
QueueNode* cur = pq->head;
while (cur)
{
QueueNode* next = cur->next;//next保存队列的下一个元素
free(cur);//将队头删掉
cur = next;
}
pq->head = NULL;
pq->tail = NULL;
}
void QueuePush(Queue* pq, QDataType x)//进队列
{
assert(pq);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
if (newnode == NULL)
{
printf("内存不足\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->head == NULL)//当队列为空时
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;//新尾插结点
}
}
void QueuePop(Queue* pq)//出队列
{//先保存下一个再头删
assert(pq);
assert(pq->head != NULL);
if (pq->head->next == NULL)//当队列只剩一个元素时
{
free(pq->head);
pq->head = NULL;
//pq->tail=NULL;
}
else
{
QueueNode* cur = pq->head->next;//用cur保存队头的下一个元素
free(pq->head);
pq->head = cur;
}
}
QDataType QueueFront(Queue* pq)//取队头数据
{
assert(pq);
assert(pq->head);
return pq->head->data;
}
QDataType QueueBack(Queue* pq)//取队尾数据
{
assert(pq);
assert(pq->tail);
return pq->tail->data;
}
int QueueEmpty(Queue* pq)//判断队列是否为空
{
assert(pq);
return pq->head == NULL ? 1 : 0;
}
int QueueSize(Queue* pq)//求队列元素个数
{
int size = 0;
assert(pq);
QueueNode* cur = pq->head;
while (cur)
{
cur = cur->next;
size++;
}
return size;
}
3、实践部分和运行截图
#include "Queue.h"
void TestQueue1()
{
Queue q;//队列结构体指针
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
while (!QueueEmpty(&q))
{
//printf("%d ",q.head->data);
printf("%d ", QueueFront(&q));
QueuePop(&q);
}
printf("\n");
QueueDestory(&q);//销毁队列
QueuePush(&q, 5);//销毁之后插入5然后取队头
printf("%d ", QueueFront(&q));
}
int main()
{
TestQueue1();
return 0;
}