C语言数据结构进阶之栈和队列的实现

yizhihongxing

C语言数据结构进阶之栈和队列的实现

什么是栈?

栈是一种数据结构,具有后进先出(LIFO)的特点。这意味着最后插入的数据最先被取出。在栈中,插入和删除数据只发生在一端,称为栈顶(top),另一端称为栈底(bottom)。下面介绍如何使用 C 语言实现栈的基本操作。

栈的基本操作

  • push:将元素压入栈顶。
  • pop:将元素从栈顶弹出。
  • isEmpty:检查栈是否为空。
  • isFull:检查栈是否已满,通常用于数组实现的栈。

栈的实现方式

  1. 数组实现

使用数组可以较简单地实现一个栈。定义一个数组存储栈元素,再定义一个栈顶指针,可以记录栈顶元素的位置。当元素入栈时,将它添加到数组末尾,并将栈顶指针加一;当元素出栈时,将栈顶指针减一,然后返回栈顶元素。

```c
#define MAX_SIZE 100
typedef struct {
int data[MAX_SIZE];
int top;
} Stack;

void push(Stack *s, int x) {
if (s->top >= MAX_SIZE) {
printf("ERROR: Stack is full\n");
return;
}
s->data[++s->top] = x;
}

int pop(Stack *s) {
if (s->top == -1) {
printf("ERROR: Stack is empty\n");
return -1;
}
return s->data[s->top--];
}

int isEmpty(Stack *s) {
return s->top == -1;
}
```

  1. 链表实现

另一种实现栈的方式是使用链表。链表是一种递归的数据结构,其结点包含了当前元素的值和一个指向下一个结点的指针。在实现栈时,可以使用链表作为储存元素的容器。在链表的头部作为栈顶,并总是在链表顶部插入和删除元素。

```c
typedef struct Node {
int data;
struct Node* next;
} Node;

typedef struct {
Node *top;
} Stack;

void push(Stack s, int x) {
Node
newNode = (Node *)malloc(sizeof(Node));
newNode->data = x;
newNode->next = s->top;
s->top = newNode;
}

int pop(Stack s) {
if (s->top == NULL) {
printf("ERROR: Stack is empty\n");
return -1;
}
Node
popped = s->top;
int data = popped->data;
s->top = popped->next;
free(popped);
return data;
}

int isEmpty(Stack *s) {
return s->top == NULL;
}
```

栈的应用

  • 判断括号匹配
  • 二叉树的非递归遍历

什么是队列?

队列(queue)是一种数据结构,具有先进先出(FIFO)的特点。这意味着先插入的数据也会最先被取出。在队列中,插入操作只发生在队列尾部,称为队尾(rear);删除操作只发生在队列头部,称为队头(front)。下面介绍如何使用 C 语言实现队列的基本操作。

队列的基本操作

  • enqueue:将元素插入队尾。
  • dequeue:将队头元素删除。
  • isEmpty:检查队列是否为空。
  • isFull:检查队列是否已满。

队列的实现方式

  1. 数组实现

使用数组可以较简单地实现一个队列。定义一个数组存储队列元素,再定义两个指针 front 和 rear,分别指向队列头和队列尾。插入操作时,将元素添加到 rear 指向的位置,并将该指针加一;删除操作时,将 front 指针加一。

```c
#define MAX_SIZE 100
typedef struct {
int data[MAX_SIZE];
int front, rear;
} Queue;

void enqueue(Queue *q, int x) {
int nextRear = (q->rear + 1) % MAX_SIZE;
if (nextRear == q->front) {
printf("ERROR: Queue is full\n");
return;
}
q->data[q->rear] = x;
q->rear = nextRear;
}

int dequeue(Queue *q) {
if (q->front == q->rear) {
printf("ERROR: Queue is empty\n");
return -1;
}
int data = q->data[q->front];
q->front = (q->front + 1) % MAX_SIZE;
return data;
}

int isEmpty(Queue *q) {
return q->front == q->rear;
}
```

  1. 链表实现

和栈一样,队列也可以用链表实现。定义一个链表结点,包含当前元素的值和一个指针,指向下一个结点。在队列中,使用一个指针 front 指向队头,并总是在链表尾部插入元素。

```c
typedef struct Node {
int data;
struct Node* next;
} Node;

typedef struct {
Node front, rear;
} Queue;

void enqueue(Queue q, int x) {
Node
newNode = (Node *)malloc(sizeof(Node));
newNode->data = x;
newNode->next = NULL;
if (q->rear) {
q->rear->next = newNode;
}
q->rear = newNode;
if (q->front == NULL) {
q->front = newNode;
}
}

int dequeue(Queue q) {
if (q->front == NULL) {
printf("ERROR: Queue is empty\n");
return -1;
}
Node
popped = q->front;
int data = popped->data;
q->front = popped->next;
if (q->front == NULL) {
q->rear = NULL;
}
free(popped);
return data;
}

int isEmpty(Queue *q) {
return q->front == NULL;
}
```

队列的应用

  • 广度优先搜索算法(BFS)
  • 模拟处理实体到达和离开事件

示例

使用栈实现计算器

思路:将中缀表达式转换成后缀表达式,再通过栈计算后缀表达式的值。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAX_SIZE 100

typedef struct {
  int data[MAX_SIZE];
  int top;
} Stack;

void push(Stack *s, int x) {
  if (s->top >= MAX_SIZE) {
    printf("ERROR: Stack is full\n");
    return;
  }
  s->data[++s->top] = x;
}

int pop(Stack *s) {
  if (s->top == -1) {
    printf("ERROR: Stack is empty\n");
    return -1;
  }
  return s->data[s->top--];
}

int isEmpty(Stack *s) {
  return s->top == -1;
}

int precedence(char op) {
  if (op == '+' || op == '-') {
    return 1;
  }
  if (op == '*' || op == '/') {
    return 2;
  }
  return 0;
}

void infixToPostfix(char *infix, char *postfix) {
  Stack s;
  s.top = -1;
  int i, j;
  char ch, x;
  for (i = 0, j = 0; infix[i] != '\0'; i++) {
    ch = infix[i];
    if (isdigit(ch)) {
      postfix[j++] = ch;
    } else if (ch == '(') {
      push(&s, '(');
    } else if (ch == ')') {
      while ((x = pop(&s)) != '(') {
        postfix[j++] = x;
      }
    } else {
      while (!isEmpty(&s) && precedence(s.data[s.top]) >= precedence(ch)) {
        postfix[j++] = pop(&s);
      }
      push(&s, ch);
    }
  }
  while (!isEmpty(&s)) {
    postfix[j++] = pop(&s);
  }
  postfix[j] = '\0';
}

int evaluatePostfix(char *postfix) {
  Stack s;
  s.top = -1;
  int i, x, y, z;
  char ch;
  for (i = 0; postfix[i] != '\0'; i++) {
    ch = postfix[i];
    if (isdigit(ch)) {
      push(&s, ch - '0');
    } else {
      y = pop(&s);
      x = pop(&s);
      switch(ch) {
        case '+': z = x + y; break;
        case '-': z = x - y; break;
        case '*': z = x * y; break;
        case '/': z = x / y; break;
        default: break;
      }
      push(&s, z);
    }
  }
  return pop(&s);
}

int main() {
  char infix[MAX_SIZE], postfix[MAX_SIZE];
  printf("Enter an infix expression: ");
  fgets(infix, MAX_SIZE, stdin);
  infixToPostfix(infix, postfix);
  printf("Postfix expression: %s\n", postfix);
  printf("Result: %d\n", evaluatePostfix(postfix));
  return 0;
}

使用队列模拟实体到达和离开事件

思路:生成随机的实体到达事件和离开事件,将它们放到两个队列中,每次取两个队列的队头元素,并比较它们的时间戳,如果离开事件的时间戳早于到达事件,说明实体已经离开,弹出节点;否则实体进入处理,从到达队列中弹出节点并加入处理队列。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct {
  int id;
  int timestamp;
} Entity;

typedef struct Node {
  Entity data;
  struct Node* next;
} Node;

typedef struct {
  Node *front, *rear;
} Queue;

void enqueue(Queue *q, Entity x) {
  Node *newNode = (Node *)malloc(sizeof(Node));
  newNode->data = x;
  newNode->next = NULL;
  if (q->rear) {
    q->rear->next = newNode;
  }
  q->rear = newNode;
  if (q->front == NULL) {
    q->front = newNode;
  }
}

Entity dequeue(Queue *q) {
  if (q->front == NULL) {
    printf("ERROR: Queue is empty\n");
    Entity e = {0, 0};
    return e;
  }
  Node *popped = q->front;
  Entity data = popped->data;
  q->front = popped->next;
  if (q->front == NULL) {
    q->rear = NULL;
  }
  free(popped);
  return data;
}

int isEmpty(Queue *q) {
  return q->front == NULL;
}

void printQueue(Queue q) {
  Node *current = q.front;
  while (current != NULL) {
    printf("%d [%d] ", current->data.id, current->data.timestamp);
    current = current->next;
  }
  printf("\n");
}

void simulate() {
  Queue arrival, departure, processing;
  arrival.front = arrival.rear = NULL;
  departure.front = departure.rear = NULL;
  processing.front = processing.rear = NULL;

  int currentTimestamp = 0, id = 0;
  int arrivalCount = 0, departureCount = 0;
  while (arrivalCount < 10) {
    currentTimestamp++;
    if (rand() % 3 != 0) {
      // generate arrival event
      Entity entity = {++id, currentTimestamp};
      printf("Entity %d arrived at time %d\n", entity.id, entity.timestamp);
      enqueue(&arrival, entity);
      arrivalCount++;
    }
    if (departure.front && currentTimestamp >= departure.front->data.timestamp) {
      // departure event occurs before next arrival
      Entity entity = dequeue(&departure);
      printf("Entity %d departed at time %d\n", entity.id, entity.timestamp);
      departureCount++;
    } else if (arrival.front) {
      // process next arrival event
      Entity entity = dequeue(&arrival);
      printf("Entity %d entered processing queue at time %d\n", entity.id, entity.timestamp);
      enqueue(&processing, entity);
    }
    if (processing.front && !departure.front) {
      // start processing if queue not empty and no event scheduled
      Entity entity = dequeue(&processing);
      Entity nextDeparture = {entity.id, currentTimestamp + rand() % 5 + 1};
      printf("Entity %d started processing at time %d\n", entity.id, currentTimestamp);
      printf("Entity %d departure scheduled at time %d\n", entity.id, nextDeparture.timestamp);
      enqueue(&departure, nextDeparture);
    }
    printf("Simulation state:\n");
    printf("Arrival queue: ");
    printQueue(arrival);
    printf("Processing queue: ");
    printQueue(processing);
    printf("Departure queue: ");
    printQueue(departure);
    printf("-------------------------\n");
  }
  printf("Simulation ended\n");
}

int main() {
  srand(time(NULL));
  simulate();
  return 0;
}

以上是“C语言数据结构进阶之栈和队列的实现”的完整攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构进阶之栈和队列的实现 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • React生命周期函数图解介绍

    下面是详细讲解 “React生命周期函数图解介绍”的完整攻略及示例说明。 1. React生命周期概述 React组件的生命周期是指组件从创建到卸载的整个过程中所经历的一系列阶段,每个阶段都具有相应的生命周期函数,这些生命周期函数可以被称为钩子函数。 React 生命周期分为三大部分 1.1 组件挂载阶段(Mounting) 组件实例被创建并插入 DOM 中…

    other 2023年6月27日
    00
  • paypal提现到派安盈无法绑定firstcenturybank账号怎么办

    如果您在PayPal上提现到派安盈账户时无法绑定First Century Bank账号,可以按照以下攻略进行操作: 确认账户信息 先,您需要确认您的派安盈账户信息是否正确。请检查您的账户名、账户号码、银行名称等信息是否正确。如果信息不正确,您需要联系派安盈客服进行修改。 联系First Century Bank客服 如果您的派安盈账户信息正确但仍然无法绑定…

    other 2023年5月9日
    00
  • C语言之单链表的插入、删除与查找

    C语言中单链表的插入、删除与查找是单链表操作中的基本操作。下面将对这三种操作进行详细讲解。 单链表基本知识 在讲解单链表的操作前,我们先来复习一下单链表的基本概念。单链表是一种链式存储结构,由若干个节点构成。每个节点由数据域和指针域组成,指针域指向下一个节点。单链表有一个头节点,头节点不存储实际的数据,其指针域指向第一个有效节点。 插入操作 单链表插入操作是…

    other 2023年6月27日
    00
  • Win10桌面版10587下载泄露 附下载地址

    Win10桌面版10587下载泄露 附下载地址攻略 简介 Win10桌面版10587是Windows 10操作系统的一个版本,该版本的下载地址泄露出来了。本攻略将详细介绍如何下载和安装Win10桌面版10587,并提供下载地址。 步骤 步骤一:获取下载地址 首先,我们需要获取Win10桌面版10587的下载地址。可以通过以下途径获取: 在线论坛:许多技术论坛…

    other 2023年8月4日
    00
  • CS1.6怎么架设服务器 cs1.6服务器架设及终极优化教程

    CS1.6服务器架设及终极优化教程 作为一款经典的第一人称射击游戏,CS1.6自然也有很多玩家想要自己架设服务器。本文将提供一份详细的攻略,帮助玩家搭建自己的CS1.6服务器,并终极优化游戏体验。 硬件要求 为了保证服务器运行顺畅,需要满足一定的硬件要求。推荐硬件配置如下: CPU:Intel Core i5或AMD Ryzen 5以上 内存:8GB或以上 …

    other 2023年6月27日
    00
  • 贝塞尔曲线(b-spline)的原理与应用

    贝塞尔曲线(b-spline)的原理与应用 什么是贝塞尔曲线? 贝塞尔曲线是一种常见的参数曲线,常用于计算机图形学、CAD、计算机辅助设计等领域。它是一条由多个控制点决定的曲线,通过这些控制点的加权平均来构成一条平滑的路径。 贝塞尔曲线原理 贝塞尔曲线的原理是基于基函数上的加权平均计算实现的。每个基函数都是一个N次多项式,它可以决定曲线在某一特定位置上的形状…

    其他 2023年3月28日
    00
  • mybatis-plus 新增/修改如何实现自动填充指定字段

    在mybatis-plus中实现自动填充指定字段的操作分为以下两个步骤: 实现填充器接口:自定义填充器实现类,实现MetaObjectHandler接口。 添加填充配置:在 mybatis-plus 的全局配置中,添加自定义的填充器及其配置。 下面我们来具体讲解如何实现自动填充指定字段: 1. 自定义填充器实现类 自定义的填充器需要实现MetaObjectH…

    other 2023年6月25日
    00
  • 逆水寒九灵什么属性重要 基本属性对九灵加成数据测试介绍

    当然,下面是关于逆水寒九灵基本属性加成数据测试的完整攻略,包含两个示例说明: 基本属性对九灵加成数据测试介绍 首先,选择一个九灵,例如「风灵」作为测试对象。 确定九灵的基本属性,包括攻击力、防御力、生命值等。 创建一个测试角色,并记录下其基本属性。 使用测试角色攻击一个固定的目标,记录下造成的伤害。 将测试角色装备上九灵「风灵」,并记录下装备后的基本属性。 …

    other 2023年10月17日
    00
合作推广
合作推广
分享本页
返回顶部