纯c语言模拟栈和队列(初学必看)

简介: 纯c语言模拟栈和队列(初学必看)

一、栈(Stack)

1.栈的概念及其结构

栈是一种特殊的线性表,在栈这个结构里,越先存进去的数据越难取出来。

这个结构就像是一个只有一端有打开的容器,越先放进去的球越在底部,想要把底部的球拿出来,就必须先把前面的求拿出来。像这种”先进后出“的结构就是栈

对于栈来说,我们只能在表尾进行插入或者删除,表

2.栈的功能

栈的基本操作主要有:栈的初始化、判空、判满、取栈顶元素、在栈顶进行插入和删除。在栈顶插入元素称为入栈,在栈顶删除元素称为出栈。

我们常用栈这种数据结构实现深度搜索。

由于栈的特性,我们只对栈顶进行取出元素或者是压入元素,所以我们在实现栈的时候需要用一个top指针来指向栈顶元素的地址或者是栈顶元素后面的地址。

3.c语言代码模拟(动态实现)

Stack.h文件:

这个文件用来声明功能函数以及栈结构体数据的定义。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int STDataType;
typedef struct Stack
{
  STDataType* _a;
  int _top;   // 栈顶
  int _capacity;  // 容量 
}Stack;
// 初始化栈 
void StackInit(Stack* ps);
// 入栈 
void StackPush(Stack* ps, STDataType data);
//打印
void StackPrint(Stack* ps);
// 出栈 
void StackPop(Stack* ps);
// 获取栈顶元素 
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数 
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps);
// 销毁栈 
void StackDestroy(Stack* ps);
 

Stack.c文件:

实现各种功能函数

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"
 
// 初始化栈 
void StackInit(Stack* ps) {
  assert(ps);
  ps->_a = NULL;
  ps->_capacity = 0;
  ps->_top = 0;
}
 
// 销毁栈 
void StackDestroy(Stack* ps) {
  assert(ps);
  free(ps->_a);
  ps->_a = NULL;
  ps->_capacity = 0;
  ps->_top = 0;
}
// 入栈 
void StackPush(Stack* ps, STDataType data) {
  assert(ps);
  if (ps->_top == ps->_capacity) {
    STDataType* temp = NULL;
    int newcap = 0;
    if (ps->_capacity == 0) {
      newcap = 4;
    }
    else {
      newcap = ps->_capacity * 2;
    }
    temp = (STDataType*)realloc(ps->_a,sizeof(STDataType) * newcap);
    if (temp == NULL) {
      perror("mallc:fail");
    }
    ps->_a = temp;
    ps->_capacity = newcap;
  }
 
  ps->_a[ps->_top] = data;
  ps->_top++;
}
 
// 出栈 
void StackPop(Stack* ps) {
  assert(ps&&ps->_top>0);
  --ps->_top;
  //return ps->_a[--ps->_top];
}
 
//打印
void StackPrint(Stack* ps) {
  assert(ps);
  printf("top=%d  cap=%d\n", ps->_top, ps->_capacity);
  for (int i = 0; i < ps->_top; i++) {
    printf("%d->", ps->_a[i]);
  }
  printf("\n");
}
// 获取栈顶元素 
STDataType StackTop(Stack* ps) {
  assert(ps&&ps->_top>0);
  return ps->_a[ps->_top - 1];
}
// 获取栈中有效元素个数 
int StackSize(Stack* ps) {
  assert(ps);
  return ps->_top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps) {
  assert(ps);
  return ps->_top == 0;
}

test.c文件:

测试栈的功能是否达到预期

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"
 
void test1() {
  Stack st;
  StackInit(&st);
  StackPush(&st, 1);
  StackPush(&st, 2);
  StackPush(&st, 3);
  StackPush(&st, 4);
  StackPrint(&st);
  printf("弹出栈顶元素\n");
  StackPop(&st);
  StackPrint(&st);
  int x =StackTop(&st);
  printf("获取栈顶元素 %d\n",x);
  StackPrint(&st);
  printf("获取栈里有效元素个数 %d\n", StackSize(&st));
  printf("栈是否为空%d\n", StackEmpty(&st));
  StackDestroy(&st);
}
int main() {
  test1();
  return 0;
}

二、队列(Queue)

1、队列的概念及其结构

只在一端进行删除操作(出队),只在另一端进行添加操作(入队)--先进先出

这个结构就像是在模拟,越先排队的人越先“打到饭”。(理论上不允许插队)

看上去像不像排队打饭的你呢?

2.队列的功能

队列 的最主要用途是异步任务和通信两个方面 异步的思路主要用来缓解瞬间压力、耗时操作、并行任务等。

队列的基本功能是入队、出队、获得队列元素个数、判断队列是否为空等操作。

在算法中我们常用队列来实现广度优先遍历

3.c语言代码模拟

Queue.h文件:

声明功能函数以及栈结构体数据的定义

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
 
typedef int QDataType;
 
// 链式结构:表示队列 
typedef struct QListNode
{
  struct QListNode* _next;
  QDataType _data;
}QNode;
 
// 队列的结构 
typedef struct Queue
{
  QNode* _front;
  QNode* _rear;
}Queue;
 
// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDataType data);
// 队头出队列 
void QueuePop(Queue* q);
//打印队列信息
void QueuePrint(Queue* q);
// 获取队列头部元素 
QDataType QueueFront(Queue* q);
// 获取队列队尾元素 
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);

Queue.c文件:

实现各种功能函数

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
 
 
// 初始化队列 
void QueueInit(Queue* q) {
  assert(q);
  q->_front = NULL;
  q->_rear = NULL;
}
//创造节点
QNode* CreatNode(QDataType x) {
  QNode* newnode =(QNode*) malloc(sizeof(QNode));
  if (newnode == NULL) {
    perror("malloc:fail");
  }
  newnode->_next = NULL;
  newnode->_data = x;
  return newnode;
}
 
// 队尾入队列 
void QueuePush(Queue* q, QDataType data) {
  assert(q);
  QNode* newnode = CreatNode(data);
  if (q->_rear == NULL) {
    q->_front=q->_rear = newnode;
  }
  else {
    q->_rear->_next = newnode;
    q->_rear = newnode;
  }
}
 
// 队头出队列 
void QueuePop(Queue* q) {
  assert(q&&q->_front!=NULL);
  QNode* head = q->_front;
  if (q->_front == q->_rear) {
    q->_front = q->_rear = NULL;
  }
  else {
    q->_front = q->_front->_next;
  }
  free(head);
  head = NULL;
}
//打印队列信息
void QueuePrint(Queue* q) {
  assert(q&&q->_rear!=NULL);
  QNode* cur = q->_front;
  printf("队头指向%d 队尾指向%d\n", q->_front->_data, q->_rear->_data);
  while (cur != NULL) {
    printf("%d->", cur->_data);
    cur = cur->_next;
  }
  printf("\n");
}
// 获取队列头部元素 
QDataType QueueFront(Queue* q) {
  assert(q&&q->_front!=NULL);
  return q->_front->_data;
}
 
// 获取队列队尾元素 
QDataType QueueBack(Queue* q) {
  assert(q&&q->_rear!=NULL);
  return q->_rear->_data;
}
 
// 获取队列中有效元素个数 
int QueueSize(Queue* q) {
  assert(q);
  int size_q = 0;
  QNode* cur = q->_front;
  while (cur) {
    size_q++;
    cur = cur->_next;
  }
  return size_q;
}
 
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q) {
  assert(q);
  return q->_front == NULL;
}
// 销毁队列 
void QueueDestroy(Queue* q) {
  assert(q&&q->_front!=NULL);
  QNode* cur = q->_front;
  while (cur) {
    QNode* temp = cur->_next;
    free(cur);
    cur = temp;
  }
  q->_front = q->_rear = NULL;
}

test.c文件:

测试队列功能

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
 
void test1() {
  Queue q;
  QueueInit(&q);
  QueuePush(&q, 1);
  QueuePush(&q, 2);
  QueuePush(&q, 3);
  QueuePush(&q, 4);
  QueuePush(&q, 5);
  QueuePrint(&q);
  printf("弹出队头元素\n");
  QueuePop(&q);
  QueuePrint(&q);
 
  printf("队列元素个数%d\n", QueueSize(&q));
  printf("队列队头元素%d 队尾元素%d\n", QueueFront(&q), QueueBack(&q));
  QueuePrint(&q);
  QueueDestroy(&q);
  printf("%p %p", q._front, q._rear);
}
 
 
int main() {
  test1();
  return 0;
}

总结

栈和队列都是数据结构中比较基础同时也是必须深刻掌握的数据结构,自己去模拟一遍它们的各种功能有利于加深自己对其的理解,同时也能提高自己的代码思维。我认为对于初学者来说是打基础的一种很好的方式。

相关文章
|
3月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
328 9
|
3月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
99 5
|
4月前
|
C语言
数组栈的实现(C语言描述)
本文介绍了如何在C语言中使用数组来实现栈的数据结构,包括栈的创建、入栈、出栈、获取栈顶元素、检查栈是否为空、获取栈的大小以及销毁栈等操作,并提供了相应的函数实现。
54 1
|
5月前
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
544 8
|
5月前
|
存储 C语言
数据结构基础详解(C语言): 栈与队列的详解附完整代码
栈是一种仅允许在一端进行插入和删除操作的线性表,常用于解决括号匹配、函数调用等问题。栈分为顺序栈和链栈,顺序栈使用数组存储,链栈基于单链表实现。栈的主要操作包括初始化、销毁、入栈、出栈等。栈的应用广泛,如表达式求值、递归等场景。栈的顺序存储结构由数组和栈顶指针构成,链栈则基于单链表的头插法实现。
697 3
|
8月前
|
C语言
C语言的栈帧
C语言的栈帧
|
8月前
|
C语言 C++
【数据结构】C语言实现:栈(Stack)与队列(Queue)
【数据结构】C语言实现:栈(Stack)与队列(Queue)
|
8月前
数据结构——栈(C语言版)
数据结构——栈(C语言版)
34 0
|
1月前
|
存储 算法 C语言
【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
62 23

热门文章

最新文章