数据结构:栈和队列

//顺序栈的结构体

#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;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值