c-数据结构(栈和队列)

栈与队列

概念

栈:只能在固定的一端进行操作;“先进后出”

  • 栈顶:可以进行插入删除的一端

  • 栈底:栈顶的对端

  • 入栈(压栈):将节点插入栈顶之上

  • 出栈(弹栈):将节点从栈顶剔除

队列:

  • 队头:可以删除节点的一端

  • 队尾:可以插入节点的一端

  • 入队:将节点插入到队尾之后

  • 出队:将队头节点从队列中剔除

顺序栈
顺序栈数据操作代码
//math3文件
----------------------------------------------------------------------------
sstack.h
----------------------------------------------------------------------------
#ifndef __SSTACK_H
#define __SSTACK_H
    
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//定义数据的类型,可以是复杂的结构体,本案例使用int
/*
typedef struct Book
{
    int id;
    char *name;
    int bookId;
    char *author;
}DATA;
*/

typedef int DATA;

//顺序栈结构体
typedef struct
{
    DATA *pData;	//栈中元素的地址
    int size;		//顺序栈的大小(数组的大小)
    int top;		//栈顶元素下标
}SeqStack;

//初始化栈
int SStack_init(SeqStack* s, int size);

//判断是否栈满
int SStack_isFull(SeqStack* s);

//判断是否栈空
int SStack_isEmpty(SeqStack* s);

//入栈|压栈
int SStack_push(SeqStack* s, DATA data);

//出栈|弹栈(指定元素)
int SStack_pop(SeqStack* s, DATA *data);

//回收栈
int SStack_free(SeqStack* s);

#endif
----------------------------------------------------------------------------
sstack.c
----------------------------------------------------------------------------
#include "sstack.h"

//初始化栈
int SStack_init(SeqStack* s, int size)
{
    //给栈中元素申请空间
    s->pData = (DATA*)calloc(sizeof(DATA), size);
    //校验
    if(s->pData == NULL)
    {
        perror("内存申请失败!");
        return -1;
    }
    //初始化
    s->size = size;
    s->top = -1;	//空栈(元素个数为 top+1 )
    
    return 0;
}


//判断是否栈满
int SStack_isFull(SeqStack* s)
{
    return s->top + 1 == s->size;
}


//判断是否栈空
int SStack_isEmpty(SeqStack* s)
{
    return s->top == -1;
}


//入栈|压栈
int SStack_push(SeqStack* s, DATA data)
{
    if(SStack_isFull(s))
    {
        printf("栈满!\n");
        return -1;
    }
    //操作栈
    s->top++;	//类似于顺序表的插入
    s->pData[s->top] = data;	//在更新后的top放数据		
    
    return 0;
}


//出栈|弹栈
int SStack_pop(SeqStack* s, DATA *data)
{
    if(SStack_isEmpty(s))
    {
        printf("栈空!\n");
        return -1;
    }
    //操作栈
    *data = s->pData[s->top];
    s->top--;
    
    return 0;
}


//回收栈
int SStack_free(SeqStack* s)
{
    if(s->pData)
    {
        free(s->pData);
        s->pData = NULL;
    }
    s->top = -1;
}
----------------------------------------------------------------------------
sstack_main.c
----------------------------------------------------------------------------
#include "sstack.h"

int main(void)
{
   SeqStack  st;
  
   SStack_init(&st,10);
   register int i = 1;
   
    for(; i <=9; i++)
    {
    	SStack_push(&st,i);
    }
    
    if(-1 == SStack_push(&st,1024))
    {
    	fprintf(stderr,"满栈,插入失败\n");
    }
    
    while(!SStack_isempty(&st))
    {
         DATA data = 0;
         SStack_pop(&st,&data);
         printf("%4d",data);         
    }
    
    printf("\n");
    
    SStack_free(&st);
   
    return 0;
}
链式栈
链式栈数据操作代码
//math4文件
----------------------------------------------------------------------------
linkstack.h
----------------------------------------------------------------------------
#ifndef __LINKSTACK_H
#define __LINKSTACK_H
   
#include <stdio.h>
#include <stdlib.h>

//定义数据存储类型
typedef int DATA;

//定义链式栈节点
typedef struct node
{
    DATA data;			//数据域
    struct node *next;	//指向下一个节点指针
} NODE;
   
//定义链式栈(就是一个装链式表的容器)
typedef struct
{
    NODE *pHead;	//栈顶指针
    int size;		//元素个数
    int sum;		//记录节点个数
}LinkStack;

//初始化链式栈
int LStack_init(LinkStack *s, int num);

// 判断栈是否已满
int LStack_isfull(LinkStack *s);

// 判断栈是否为空
int LStack_isempty(LinkStack *s);

// 压栈/入栈
int LStack_push(LinkStack *s,DATA data);

// 弹栈/出栈
int LStack_pop(LinkStack *s,DATA *data);

// 回收栈
int LStack_free(LinkStack *s);

#endif
----------------------------------------------------------------------------
linkstack.c
----------------------------------------------------------------------------
#include "linkstack.h"

    
//初始化链式栈
int LStack_init(LinkStack *s, int num)
{
    s->pHead = NULL;
    s->size = num;
    s->num = 0;		//用来计数
    
    return 0;
}


// 判断栈是否已满
int LStack_isfull(LinkStack *s)
{
    return s->num == s->size;
}


// 判断栈是否为空
int LStack_isempty(LinkStack *s)
{
    return s->num == 0;
}


// 压栈/入栈
int LStack_push(LinkStack *s,DATA data)
{
    //判断是否栈满
    if(LStack_isfull(s))
    {
        return -1;
    }
    
    NODE* p = s->pHead;
    if(!p)
    {
        return -1;
    }
    //给新节点赋初值,采用头插法
    p->data = data;
    p->next = s->pHead;
    s->pHead = p;
    
    (s->num)++;	//计数
    
    return 0;
}


// 弹栈/出栈
int LStack_pop(LinkStack *s,DATA *data)
{
    //判断是否栈空
    if(LStack_isempty(s))
    {
        return -1;
    }
    //创建一个空节点指向栈顶
    NODE* p = s->pHead;
    
    if(!p)
    {
        return -1;
    }
    //取出栈顶数据,然后栈顶向下移动
    //注意区分 pHead:栈顶指针	next:链表指针	s:栈		p:链表
    *data = p->data;
    s->pHead = p->next;
    free(p);	//思考:为什么不是free(s)
    //取出后可以释放空间
    (s->num)--;
    
    return 0;
}


// 回收栈(本质:回收链表节点)
int LStack_free(LinkStack *s)
{
    NODE* p = s->pHead, *q = NULL;
    
    while(p)
    {
        q = p;
        p = p->next;
        free(q);
    }
    s->pHead = NULL;
    s->num = 0;
    
    return 0;
}
----------------------------------------------------------------------------
linkstack_main.c
----------------------------------------------------------------------------
#include "linkstack.h"

int main(void)
{
    LinkStack  st;
    LStack_init(&st,10);
    register int i = 1;
   
    //入栈
    for(; i <= 10; i++)
    {
       LStack_push(&st,i);
    }
    
    if(-1 == LStack_push(&st,1024))
    {
       fprintf(stderr,"满栈,插入失败\n");
    }
    
    //出栈
    while(!LStack_isempty(&st))
    {
         DATA   data = 0;
         LStack_pop(&st,&data);
         printf("%4d",data);         
    }
    
    printf("\n");
    
    //回收栈
    LStack_free(&st);
    
    return 0;  
}
顺序队列
顺序队列数据操作代码
//math5文件
--------------------------------------------------------------------------------------------------
squeue.h
--------------------------------------------------------------------------------------------------
#ifndef __SQUEUE_H
#define __SQUEUE_H
   
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int DATA;

//创建顺序队列
typedef struct
{
    DATA *pData;	//队列入口
    int size;		//队列总容量
    int head;		//队头元素下标
    int tail;		//队尾元素下标
}SQueue;

//初始化队列
int SQ_init(SQueue *q, int num);

// 判断顺序队列是否队满
int SQ_isfull(SQueue *q);

// 判断顺序队列是否队空
int SQ_isempty(SQueue *q);

// 顺序队列插入数据
int SQ_push(SQueue *q,DATA data);

// 顺序队列输出数据
int SQ_pop(SQueue *q,DATA *data);

// 回收顺序队
int SQ_free(SQueue *q);
    
#endif
--------------------------------------------------------------------------------------------------
squeue.c
--------------------------------------------------------------------------------------------------
#include "squeue.h"


//初始化队列
int SQ_init(SQueue *q, int num)
{
    //创建队列空间
    q->pData = (DATA*)calloc(sizeof(DATA),num);
    
    if(q->pData == NULL)
    {
        return -1;
    }
    q->size = num;
    q->head = q->tail = 0;	//空的队列,后期再插入元素
    
    return 0;
}


// 判断顺序队列是否队满
int SQ_isfull(SQueue *q)
{
    //队头下标始终为0
    return (q->tail + 1) % q->size == q->head;
}


// 判断顺序队列是否队空
int SQ_isempty(SQueue *q)
{
    return q->head == q->tail;
}


// 顺序队列插入数据
int SQ_push(SQueue *q,DATA data)
{
    //判断是否满队
    if(SQ_isfull(q))
    {
        return -1;
    }
    
    类似于栈,看图,先全部集中到队头,插入时 tail 会变化(逐步往后移动),然后打印的时候从 head 开始(依次往后移动)
    其实本质就是尾插法
    q->pData[q->tail] = data;
    //(q->tail+1):下标加1
    //(q->tail+1) % q->size:防止越界
    q->tail = (q->tail + 1) % q->size;
    //若不循环:
    
    return 0;
}


// 顺序队列输出数据
int SQ_pop(SQueue *q,DATA *data)
{
    if(SQ_isempty(q))
    {
        return -1;
    }
    
    *data = q->pData[q->head];
    q->head = (q->head + 1) % q->size;
    
    return 0;
}


// 回收顺序队
int SQ_free(SQueue *q)
{
    if(q->pData)
    {
        free(q->pData);
        q->pData = NULL;
    }
    q->head = q->tail = 0;
}
链式队列
链式队列数据操作代码
//math6文件
--------------------------------------------------------------------------------------------------
linkSqueue.h
--------------------------------------------------------------------------------------------------
#ifndef __SQUEUE_H
#define __SQUEUE_H
   
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int DATA;

//定义链式队列节点
typedef struct node
{
    DATA data;
    struct node *next;
}NODE;

//定义链式队列
typedef struct
{
    NODE *pHead;	//头指针
    NODE *pTail;	//尾指针
    int size;		//队列当前元素个数
    int num;		//计数
}LinkQueue;

//初始化链式队列
void LQ_init(LinkQueue *, int);

//判断链式队列是否队满
int  LQ_isfull(LinkQueue *);

//判断链式队列是否队空
int  LQ_isempty(LinkQueue *);

//链式队列插入数据
int  LQ_push(LinkQueue *, DATA);

//链式队列输出数据
int  LQ_pop(LinkQueue *, DATA *);

//回收链式队列
int LQ_free(LinkQueue *);

#endif
--------------------------------------------------------------------------------------------------
linkSqueue.c
--------------------------------------------------------------------------------------------------
#include "linkSqueue.h"


//初始化链式队列
void LQ_init(LinkQueue *q,int size)
{
    q->pHead = q->pTail = NULL;
    q->size = size;
    q->num = 0;
}


//判断链式队列是否队满
int  LQ_isfull(LinkQueue *q)
{
    return q->num == q->size;
}


//判断链式队列是否队空
int  LQ_isempty(LinkQueue *q)
{
    return q->num == 0;
}


//链式队列插入数据
int  LQ_push(LinkQueue *q,DATA data)
{
    //检验是否队满
    if(LQ_isfull(q))
    {
        return -1;
    }
    //创建新节点并且初始化
    NODE* pNew = (NODE*)malloc(sizeof(NODE));
    if(!pNew)
    {
        return -1;
    }
    pNew->data = data;
    pNew->next = NULL;
    参考顺序队列思想
    //第一种情况,链表为空
    if(!(q->pTail))
    {
        q->pHead = q->pTail = pNew;
    }
    else	//第二种情况,链表不为空
    {
        q->pTail->next = pNew;
        q->pTail = pNew;
    }
    q->num++;
    
    return 0;
}


//链式队列输出数据
int  LQ_pop(LinkQueue *q,DATA *data)
{
    //判断是否队空
    if(LQ_isempty(q))
    {
        return -1;
    }
    
    //只要队列非空,就取首节点以及数据
    NODE* pNew = q->pHead;
    *data = pNew->data;
    
    //第一种情况,队列只有一个节点
    if(pNew == q->pTail)
    {
        q->pHead = q->pTail = NULL;
    }
    else	//第二种情况,队列有多个节点
    {
        p->pHead = pNew->next;
    }
    
    free(pNew);
    q->num--;
    
    return 0;
}


//回收链式队列
int LQ_free(LinkQueue *q)
{
    NODE* pNew = q->pHead, *p = NULL;
    
    while(pNew)
    {
        p  = pNew;
        pNew = pNew->next;
        free(p);
    }
    q->pHead = q->pTail = NULL;
    q->num = 0;
    
    return 0;
}
--------------------------------------------------------------------------------------------------
linkSqueue_main.c
--------------------------------------------------------------------------------------------------
#include "LinkSqueue.h"
    
int main()
{
    LinkQueue queue;
    
    LQ_init(&queue,10);
    register  int i = 1; 
    
    for(; i <= 10 ; i++)
    {
       LQ_push(&queue, i);
    }
    
    if( -1 == LQ_push(&queue,1024))
    {
      fprintf(stderr,"满队,入队失败!\n");
    }
    
    while(!LQ_isempty(&queue))
    {
        DATA   data;
        LQ_pop(&queue,&data);
        printf("%4d",data);
    }
    printf("\n");
    
    LQ_free(&queue);
    
    return 0; 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值