嵌入式学习数据结构(三)栈 链式 循环队列

目录

一.栈

1.系统栈

2.顺序表(数组)---》顺序栈

3.链式栈:

头文件

创建链表

入栈(压栈)

出栈(弹栈)

获取栈顶元素

遍历

销毁链式栈

二.队列

1.顺序队列

2.链式队列

头文件

创建队列

入队

出队

获取队头元素

遍历

销毁队列

主函数

3.循环队列

头文件

创建队列

判空

判满

入队

出队

遍历

获取队头元素

销毁队列

主函数


一.栈

1.系统栈

数据结构中的栈:

只允许从一端进行数据的插入和删除的线性存储结构,称之为栈结构

特点:先进后出: FILO

2.顺序表(数组)---》顺序栈

满增栈、满减栈、空增栈、空减栈

满栈、空栈:栈顶所在位置是否存在数据

增栈、减栈:按照栈的生长方向区分

3.链式栈:

头文件

cpp 复制代码
#ifndef __STACK_H__
#define __STACK_H__
 
typedef int Data_type_t;
typedef struct stnode
{
  Data_type_t data;
  struct stnode *pnext;
} STNode_t;
 
typedef struct stack
{
  STNode_t *ptop;
  int clen;
} Stack_t;
 
Stack_t *create_stack();
int is_empty_stack(Stack_t *pstack);
int push_stack(Stack_t *pstack, Data_type_t data);
int pop_stack(Stack_t *pstack, Data_type_t *pdata);
void stack_for_each(Stack_t *pstack);
int get_top_stack(Stack_t *pstack, Data_type_t *pdata);
void destroy_stack(Stack_t **ppstack);
 
#endif

创建链表

cpp 复制代码
Stack_t *create_stack()
{
  Stack_t *pstack = malloc(sizeof(Stack_t));
  if (pstack == NULL)
    {
      printf("malloc error\n");
      return NULL;
    }
  pstack->ptop = NULL;
  pstack->clen = 0;
 
  return pstack;
}

入栈(压栈)

cpp 复制代码
int push_stack(Stack_t *pstack, Data_type_t data)
{
  STNode_t *pnode = malloc(sizeof(STNode_t));
  if (pnode == NULL)
    {
      printf("malloc error\n");
      return -1;
    }
  pnode->pnext = NULL;
  pnode->data = data;
 
  pnode->pnext = pstack->ptop;
  pstack->ptop = pnode;
  pstack->clen++;
}

出栈(弹栈)

cpp 复制代码
int pop_stack(Stack_t *pstack, Data_type_t *pdata)
{
  if (pstack->ptop == NULL)
    {
      return -1;
    }
  else
    {
      STNode_t *ptemp = pstack->ptop;
      pstack->ptop = ptemp->pnext;
      if (pdata != NULL)
        {
          *pdata = ptemp->data;
        }
      free(ptemp);
      pstack->clen--;
      return 0;
    }
}

获取栈顶元素

cpp 复制代码
int get_top_stack(Stack_t *pstack, Data_type_t *pdata)
{
  if (NULL == pstack->ptop)
    {
      return -1;
    }
  if (NULL == pdata)
    {
      return -1;
    }
  *pdata = pstack->ptop->data;
  return 0;
}

遍历

cpp 复制代码
void stack_for_each(Stack_t *pstack)
{
  STNode_t *ptemp = pstack->ptop;
 
  while (ptemp != NULL)
    {
      printf("%d", ptemp->data);
      ptemp = ptemp->pnext;
    }
  printf("\n");
}

销毁链式栈

cpp 复制代码
void destroy_stack(Stack_t **ppstack)
{
  while (!is_empty_stack(*ppstack))
    {
      pop_stack(*ppstack, NULL);
    }
  free(*ppstack);
  *ppstack = NULL;
}

主函数

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
 
int main(void)
{
  Data_type_t data;
  Stack_t* pstack = create_stack();
  if (NULL == pstack)
    {
      return -1;
    }
  push_stack(pstack, 0);
  push_stack(pstack, 1);
  push_stack(pstack, 2);
  push_stack(pstack, 3);
  push_stack(pstack, 4);
  stack_for_each(pstack);
  int ret = pop_stack(pstack, &data);
  if (ret == 0)
    {
      printf("data = %d\n", data);
    }
  stack_for_each(pstack);
  ret = get_top_stack(pstack, &data);
  if (0 == ret)
    {
      printf("top : %d\n", data);
    }
  destroy_stack(&pstack);
}

二.队列

允许从一端进行数据的插入,另一端进行数据的删除的线性存储结构,称为队列结构。

插入操作:入队操作,插入这端称为队列的队尾。

删除操作:出队操作,删除这端称为队列的队头。

特点:先进先出(FIFO)

应用:数据缓存

1.顺序队列

顺序表---->顺序队列---->假溢出问题---->循环队列

判空:队头,队尾处于同一位置

判满:当队尾+1跟上队头时

循环队列为了区分队空和队满,将少存储一个数据

2.链式队列

头文件

cpp 复制代码
#ifndef __LQUEUE_H__
#define __LQUEUE_H__


typedef int Data_type_t;

typedef struct lqnode
{
    Data_type_t data;
    struct lqnode *pnext;
}LQNode_t;


typedef struct lqueue
{
    LQNode_t *phead;
    LQNode_t *ptail;
    int clen;
}LQueue_t;


extern LQueue_t *create_link_queue();
extern void link_queue_for_each(LQueue_t *plq);
extern int push_link_queue(LQueue_t *plq, Data_type_t data);
extern int is_empty_link_queue(LQueue_t *plq);
extern int pop_link_queue(LQueue_t *plq, Data_type_t *pdata);
extern void destroy_link_queue(LQueue_t **pplq);
extern int get_queue_head(LQueue_t *plq, Data_type_t *pdata);

#endif

创建队列

cpp 复制代码
LQueue_t* create_lqueue()
{
  LQueue_t* plqueue = malloc(sizeof(LQueue_t));
  if (NULL == plqueue)
    {
      printf("malloc error\n");
      return NULL;
    }
  plqueue->phead = NULL;
  plqueue->ptail = NULL;
  plqueue->clen = 0;
  return plqueue;
}

入队

cpp 复制代码
int in_plqueue_tail(LQueue_t* plqueue, Data_type_t data)
{
  LQNode_t* pnode = malloc(sizeof(LQNode_t));
  if (pnode == NULL)
    {
      printf("malloc error\n");
      return -1;
    }
  pnode->pnext = NULL;
  pnode->data = data;
  if (is_empty_plqueue(plqueue))
    {
      plqueue->phead = pnode;
      plqueue->ptail = pnode;
      plqueue->clen++;
    }
  else
    {
      plqueue->ptail->pnext = pnode;
      plqueue->ptail = pnode;
      plqueue->clen++;
    }
  return 0;
}

出队

cpp 复制代码
int out_plqueue_head(LQueue_t* plqueue)
{
  LQNode_t* ptemp = plqueue->phead;
  if (is_empty_plqueue(plqueue))
    {
      return -1;
    }
  if (plqueue->phead == plqueue->ptail)
    {
      free(ptemp);
      plqueue->phead = NULL;
      plqueue->ptail = NULL;
      plqueue->clen--;
    }
  else
    {
      plqueue->phead = ptemp->pnext;
      free(ptemp);
      plqueue->clen--;
    }
}

获取队头元素

cpp 复制代码
int get_top_plqueue(LQueue_t* plqueue, Data_type_t* data)
{
  if (is_empty_plqueue(plqueue))
    {
      return -1;
    }
  *data = plqueue->phead->data;
  return 0;
}

遍历

cpp 复制代码
int plqueue_for_each(LQueue_t* plqueue)
{
  LQNode_t* ptemp = plqueue->phead;
 
  if (is_empty_plqueue(plqueue))
    {
      return -1;
    }
  while (ptemp != NULL)
    {
      printf("%2d", ptemp->data);
      ptemp = ptemp->pnext;
    }
  printf("\n");
}

销毁队列

cpp 复制代码
int destory_plqueue(LQueue_t** pplqueue)
{
  while (!is_empty_plqueue(*pplqueue))
    {
      out_plqueue_head(*pplqueue);
    }
  free(*pplqueue);
  *pplqueue = NULL;
}

主函数

cpp 复制代码
#include <stdio.h>
#include "lqueue.h"
int main(void)
{
  LQueue_t* plqueue = create_lqueue();
  if (plqueue == NULL)
    {
      return -1;
    }
  in_plqueue_tail(plqueue, 0);
  in_plqueue_tail(plqueue, 1);
  in_plqueue_tail(plqueue, 2);
  in_plqueue_tail(plqueue, 3);
  in_plqueue_tail(plqueue, 4);
  out_plqueue_head(plqueue);
  plqueue_for_each(plqueue);
  Data_type_t data;
  int ret = get_top_plqueue(plqueue, &data);
  if (ret == 0)
    {
      printf("top = %d\n", data);
    }
  destory_plqueue(&plqueue);
}

3.循环队列

头文件

cpp 复制代码
#ifndef __SEQQUE_H_
#define __SEQQUE_H_
 
#define SEQQUE_MAX_LEN 10
 
typedef int Data_type_t;
 
typedef struct seqque
{
  Data_type_t *pbase;
  int head;
  int tail;
} Seqque_t;
 
extern Seqque_t *create_seqque();
extern int is_full_seqque(Seqque_t *psq);
extern int is_empty_seqque(Seqque_t *psq);
extern int push_seqque(Seqque_t *psq, Data_type_t data);
extern void seqque_for_each(Seqque_t *psq);
extern int out_seqque(Seqque_t *psq, Data_type_t *data);
extern int get_head_seqque(Seqque_t *psq, Data_type_t *data);
extern void destory_seqque(Seqque_t **psq);
#endif

创建队列

cpp 复制代码
Seqque_t *create_seqque()
{
  Seqque_t *psq = malloc(sizeof(Seqque_t));
  if (NULL == psq)
    {
      printf("malloc error\n");
      return NULL;
    }
  psq->head = 0;
  psq->tail = 0;
  psq->pbase = malloc(sizeof(Data_type_t) * SEQQUE_MAX_LEN);
  if (NULL == psq->pbase)
    {
      printf("malloc error\n");
      return NULL;
    }
 
  return psq;
}

判空

cpp 复制代码
int is_empty_seqque(Seqque_t *psq)
{
  if (psq->head == psq->tail)
    {
      return 1;
    }
  return 0;
}

判满

cpp 复制代码
int is_full_seqque(Seqque_t *psq)
{
  if ((psq->tail + 1) % SEQQUE_MAX_LEN == psq->head)
    {
      return 1;
    }
  return 0;
}

入队

cpp 复制代码
int push_seqque(Seqque_t *psq, Data_type_t data)
{
  if (is_full_seqque(psq))
    {
      printf("seqque is full\n");
      return -1;
    }
 
  psq->pbase[psq->tail] = data;
  psq->tail = (psq->tail + 1) % SEQQUE_MAX_LEN;
 
  return 0;
}

出队

cpp 复制代码
int out_seqque(Seqque_t *psq, Data_type_t *data)
{
  if (is_empty_seqque(psq) || NULL == data)
    {
      printf("seqque is empty\n");
      return -1;
    }
 
  *data = psq->pbase[psq->head];
  psq->head = (psq->head + 1) % SEQQUE_MAX_LEN;
  return 0;
}

遍历

cpp 复制代码
void seqque_for_each(Seqque_t *psq)
{
  for (int i = psq->head; i != psq->tail; i = (i + 1) % SEQQUE_MAX_LEN)
    {
      printf("%d ", psq->pbase[i]);
    }
  printf("\n");
}

获取队头元素

cpp 复制代码
int get_head_seqque(Seqque_t *psq, Data_type_t *data)
{
  if (is_empty_seqque(psq) || NULL == data)
    {
      printf("seqque is empty\n");
      return -1;
    }
 
  *data = psq->pbase[psq->head];
}

销毁队列

cpp 复制代码
void destory_seqque(Seqque_t **psq)
{
  free((*psq)->pbase);
  free(*psq);
  *psq = NULL;
}

主函数

cpp 复制代码
#include <stdio.h>
#include "seqque.h"
 
int main(void)
{
  Seqque_t *psq = create_seqque();
  if (NULL == psq)
    {
      return -1;
    }
 
  for (int i = 0; i < 10; i++)
    {
      push_seqque(psq, i);
    }
  Data_type_t data;
  seqque_for_each(psq);
  out_seqque(psq, &data);
  if (out_seqque(psq, &data) == 0)
    {
      printf("%d\n", data);
    }
  seqque_for_each(psq);
  destory_seqque(&psq);
 
  return 0;
}
相关推荐
黄敬峰2 小时前
深入理解算法核心:从递归思想、数组扁平化到快速排序
算法
得物技术3 小时前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六7 小时前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程
胡萝卜术7 小时前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
Asize8 小时前
初识DFS 与 BFS:递归、队列与图遍历
算法
罗西的思考21 小时前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
CSharp精选营1 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
美团技术团队1 天前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC2 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode