//顺序栈的结构体
#define N 5
typedef struct
{
int data[N]; //data数组,用来保存有效数据
int top;//top栈针,top理解方式和顺序表中last一样,代表有效元素的个数
//同时我们在使用的时候,会将top,当做数组的下标来使用
}seqstack_t;
1.创建一个空的栈 === 创建一个空的顺序表
2.入栈 === 在顺序表的尾巴上插入一个数据 有效元素个数+1
3.出栈 === 删除顺序表的尾巴 尾巴里面的数据域返回 有效元素个数-1
4.判断栈是否为满 == 判断顺序表是否未满
5.判断栈是否为空 == 判断顺序表是否为空
6.获取栈顶元素 == 将顺序表的尾巴节点里面的数据域返回
7.清空栈 == 清空顺序表
#include <stdio.h>
#include <stdlib.h>
#define N 5
typedef struct
{
int data[N];
int top;//栈针,top代表有效元素的个数,同时在使用的时候,top也当做下标来使用
}seqstack_t;
//1.创建一个空的栈
seqstack_t* createEmptyStack()
{
//申请一个结构体空间大小
seqstack_t* p = malloc(sizeof(seqstack_t));
if(p == NULL)
{
printf("createEmptyStack malloc failed!!\n");
return NULL;
}
p->top = 0;//空栈,有效元素个数为0
return p;
}
//2.判断栈是否为满,栈满 返回1,未满返回0
int isFullStack(seqstack_t* p)
{
return p->top == N ? 1 : 0;//有效元素个数 == 数组最大长度,栈满
}
//3.判断栈是否为空,栈空,返回1,未空返回0
int isEmptyStack(seqstack_t* p)
{
return p->top == 0 ? 1 : 0;//有效元素个数 == 0 栈空
}
//4.入栈(本质就是在数组的尾巴,进行插入操作)
int pushStack(seqstack_t* p, int x)
{
//0.容错判断
if(isFullStack(p))//如果栈满结束
{
printf("isFullStack!!!\n");
return -1;
}
//1.入栈,用top来当做数组中的下标来使用
p->data[p->top] = x;
//2.有效元素个数+1
p->top++;
return 0;
}
//5.出栈,将出栈元素的值返回(本质就是在数组尾巴,删除操作)
int popStack(seqstack_t* p)
{
//0.容错判断
if(isEmptyStack(p))
{
printf("isEmptyStack!!\n");
return -1;
}
//1.p->top--,有两个目的:1. 有效元素个数-1 2.得到出栈元素的下标
p->top--;
//2.有效元素个数-1之后,正好得到,出栈的最后一个有效元素的下标
return p->data[p->top];
}
//6.清空栈
void clearStack(seqstack_t* p)
{
p->top = 0;
}
//7.获取栈顶元素的值,并不是让栈顶元素删除,出栈
int getTopValue(seqstack_t* p)
{
if(isEmptyStack(p))
{
printf("isEmptyStack!!\n");
return -1;
}
return p->data[p->top-1];//将栈顶的元素返回值,p->top-1得到最后一个有效元素的下标
}
//showBinNum(p, 10)
void showBinNum(seqstack_t* p, int num)
{
//0 1 0 1
//求num的每一个二进制位入栈
//再全部出栈打印
}
int main(int argc, const char *argv[])
{
seqstack_t* p = createEmptyStack();//创建一个空的栈,申请一个结构体空间大小
pushStack(p,10);
pushStack(p,20);
pushStack(p,30);
pushStack(p,40);
pushStack(p,50);
pushStack(p,60);//入栈失败,因为N是5,最多装5个数
//将栈内的所有元素出栈
while(!isEmptyStack(p))//只要栈不为空,就进入循环,执行出栈操作,当栈空的时候,循环结束
{
//将出栈的每个元素打印输出
printf("%d ",popStack(p));//入栈的顺序是10 20 30 40 50,出栈的顺序是 50 40 30 20 10
}
printf("\n");
return 0;
}
队列
(1)只能在两端进行插入和删除操作的线性表(在队列头进行删除,队列的尾进行插入)
(2)规则
先进先出,后进后出
队列:去银行排队,先来的,先办理业务
(3)有两个指针
存数据端(rear)//rear 后方 队尾 如果是插入,入队列,需要rear当做下标 p->data[p->rear]
取数据端(front)//front 前方 队头 如果是删除, 出队列,需要front当做下标 p->data[p->front]
用数组实现的队列称为循环队列 也叫顺序队列
用链表实现的队列叫 链式队列
顺序队列(顺序存储)和链式队列(链式存储)最大的区别是???? 存储结构不一样
//queue 队列
//sequence //顺序
#define N 5
typedef struct
{
int data[N];
int rear; //后面 队列尾 插入 p->data[p->rear] 存数据端
int front;//前面 队列头 删除 p->data[p->front] 取数据端
}sequeue_t;
//创建一个空的队列
//入列
//出列
//判断对队列是否为空
//判断队列是否为满
//求队列的长度
********重点**********
+++++++++++++++++++++++++++++++++++++++++++++++++
循环队列中最多存储N-1个元素,N代表数组的元素个数
//造成这个结果原因是什么????
因为 p->rear 和 p->front相等的时候,我们认为此时的队列是空队列
判断满的时候 if((p->rear+ 1)%N == p->front)
+++++++++++++++++++++++++++++++++++++++++++++++++
队列
1.创建一个空的队列
2.入列
3.出列
4.判断队列是否为空
5.判断队列是否为满
6.求队列的长度
#include <stdio.h>
#include <stdlib.h>
#define N 5
typedef struct
{
int data[N];
int rear;//后方 队尾 在插入操作(入队)的时候,用rear来当做数组的下标
int front;//前方 队头 在删除操作(出队)的时候,用front来当做数组的下标
}sequeue_t;
//1.创建一个空的队列
sequeue_t* createEmptyQueue()
{
//申请一个结构体空间的大小
sequeue_t* p = malloc(sizeof(sequeue_t));
if(p == NULL)
{
printf("createEmptyQueue malloc failed!!\n");
return NULL;
}
//因为是空的队列,只要p->rear 和 p->front的值相等就是一个空的队列
p->rear = 0;
p->front = 0;
return p;
}
//2. 判断队列是否为满 满返回值1 未满返回0
int isFullQueue(sequeue_t* p)
{
//因为rear和front相当代表空,所以提前判断rear+1的位置是否和front相等来代表队列为满
//浪费了一个存储位置
return (p->rear+1)%N == p->front ? 1 : 0;
}
//3.判断队列是否为空 空返回值1,未空返回值是0
int isEmptyQueue(sequeue_t* p)
{
return p->rear == p->front ? 1 : 0;
}
//4.入列,在队尾插入,用rear当做下标,rear后面的意思
int inQueue(sequeue_t* p, int x)
{
//0.容错判断,队列满,提前结束函数
if(isFullQueue(p))
{
printf("isFullQueue!!\n");
return -1;
}
//1.入列,用rear当做数组的下标,插入数据 rear代表的是队列尾巴的后一个位置的下标
p->data[p->rear] = x;
//2.rear++,向后移动一个位置
p->rear = (p->rear+1) % N;
return 0;
}
//5.出列,在队头删除,用front当做下标,front前面的意思
int outQueue(sequeue_t* p)
{
//0.容错判断,队列空,提前结束函数
if(isEmptyQueue(p))
{
printf("isEmptyQueue!!\n");
return -1;
}
//1.出列 ,将队头的元素,暂时存储到x中
//front的位置,就是队头第一个有效元素的下标
int x = p->data[p->front];
//2.front++ 向后移动一个位置
p->front = (p->front+1) % N;//front++向后移动
return x;
}
int getLengthQueue(sequeue_t* p)
{
/*
//方法一:
if(p->rear >= p->front)
return p->rear - p->front;
else//p->rear < p->front 按道理rear肯定要>front,rear变小的原因,是因为%N,所以可以先加上N,再减去front
return p->rear + N - p->front;
*/
//方法二:
return (p->rear + N - p->front) % N;
}
int main(int argc, const char *argv[])
{
sequeue_t* p = createEmptyQueue();
inQueue(p,10);
inQueue(p,20);
inQueue(p,30);
inQueue(p,40);
printf("len is %d\n",getLengthQueue(p));
inQueue(p,50);//50入列失败,数组最大长度是5,最多存储N-1个有效元素,浪费一个存储位置
while(!isEmptyQueue(p))//只要队列不为空,就出列
{
printf("%d ",outQueue(p));//入列的顺序10 20 30 40,出列的顺序 10 20 30 40
}
printf("\n");
return 0;
}