C语言数据结构之栈和队列的实现及应用

C语言数据结构之栈和队列的实现及应用

什么是栈和队列?

栈是一种具有后进先出(LIFO)特性的线性数据结构,可以理解为一个只能在一端进行插入和删除操作的数据结构。通常称插入元素的一端为栈顶,删除元素的一端为栈底。

队列是一种具有先进先出(FIFO)特性的线性数据结构,可以理解为一个只能在两端进行插入和删除操作的数据结构。一端进行插入操作,称之为队尾,一端进行删除操作,称之为队首。

栈的实现及应用

栈的实现

在C语言中实现栈用数组和链表两种方式。下面我们讨论数组实现方式。

首先需要定义一个数组和一个指针,指针指向栈顶元素。实现push和pop操作时,修改指针位置并操作数组内容即可。

#define MAX_SIZE 1000

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

void push(Stack *s, int x) {
    if(s->top < MAX_SIZE) {
        s->a[s->top++] = x;
    } else {
        printf("Stack overflow!\n");
    }
}

int pop(Stack *s) {
    if(s->top > 0) {
        return s->a[--s->top];
    } else {
        printf("Stack underflow!\n");
        return -1;
    }
}

栈的应用

常见的栈的应用场景有表达式求值、括号匹配、迷宫问题等,下面我们简单介绍两个示例。

示例1:表达式求值

算术表达式通常是用中缀表示,即操作数在中间,操作符在两侧。为了求值表达式,我们通常将中缀表达式转成后缀表达式,然后用栈求值。下面是示例代码:

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

int isOp(char c) {
    return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';
}

void infix2postfix(char *infix, char *postfix) {
    Stack s;
    s.top = 0;
    int i, j;
    for(i = 0, j = 0; infix[i]; i++) {
        if(!isOp(infix[i])) {
            postfix[j++] = infix[i];
        } else if(infix[i] == ')') {
            while(s.top && s.a[s.top-1] != '(') {
                postfix[j++] = s.a[--s.top];
            }
            if(s.top) {
                s.top--;
            }
        } else {
            while(s.top && getPrior(s.a[s.top-1]) >= getPrior(infix[i])) {
                postfix[j++] = s.a[--s.top];
            }
            s.a[s.top++] = infix[i];
        }
    }
    while(s.top) {
        postfix[j++] = s.a[--s.top];
    }
    postfix[j] = '\0';
}

int postfixEval(char *postfix) {
    Stack s;
    s.top = 0;
    int i, a, b, c;
    for(i = 0; postfix[i]; i++) {
        if(!isOp(postfix[i])) {
            push(&s, postfix[i] - '0');
        } else {
            a = pop(&s);
            b = pop(&s);
            switch(postfix[i]) {
                case '+':
                    c = a + b;
                    break;
                case '-':
                    c = b - a;
                    break;
                case '*':
                    c = a * b;
                    break;
                case '/':
                    c = b / a;
                    break;
            }
            push(&s, c);
        }
    }
    return pop(&s);
}

示例2:括号匹配

括号匹配问题也可以使用栈来解决。我们遍历字符串,并用栈记录左括号,遇到右括号时出栈一个左括号并匹配,如果不匹配直接返回。

int isMatch(char a, char b) {
    return (a == '(' && b == ')') || (a == '[' && b == ']') || (a == '{' && b == '}');
}

int isBalanced(char *s) {
    Stack stk;
    stk.top = 0;
    int i;
    for(i = 0; s[i]; i++) {
        if(s[i] == '(' || s[i] == '[' || s[i] == '{') {
            push(&stk, s[i]);
        } else if(s[i] == ')' || s[i] == ']' || s[i] == '}') {
            if(!stk.top || !isMatch(stk.a[stk.top-1], s[i])) {
                return 0;
            }
            stk.top--;
        }
    }
    return stk.top == 0;
}

队列的实现及应用

队列的实现

在C语言中实现队列用数组和链表两种方式。下面我们讨论数组实现方式。

与栈相似,需要定义一个数组和两个指针,一个指向队头元素,一个指向队尾元素。实现enqueue和dequeue操作时,修改指针位置并操作数组内容即可。

#define MAX_SIZE 1000

typedef struct {
    int a[MAX_SIZE];
    int front, rear;
} Queue;

void enqueue(Queue *q, int x) {
    if(q->rear < MAX_SIZE) {
        q->a[q->rear++] = x;
    } else {
        printf("Queue overflow!\n");
    }
}

int dequeue(Queue *q) {
    if(q->front < q->rear) {
        return q->a[q->front++];
    } else {
        printf("Queue underflow!\n");
        return -1;
    }
}

队列的应用

常见的队列的应用场景有FIFO算法、消息队列、排队系统等,下面我们简单介绍两个示例。

示例1:FIFO算法

FIFO(First In First Out)算法是一种页面置换算法,也称先进先出算法。它选择最早调入内存的页面进行置换。

#define MEM_SIZE 4

int pageFaults(int *references, int n) {
    Queue q;
    q.front = q.rear = 0;
    int mem[MEM_SIZE] = {0};
    int i, j, faults = 0;
    for(i = 0; i < n; i++) {
        int found = 0;
        for(j = 0; j < MEM_SIZE; j++) {
            if(references[i] == mem[j]) {
                found = 1;
                break;
            }
        }
        if(found) {
            // already in memory
        } else if(q.rear < MEM_SIZE) {
            mem[q.rear++] = references[i];
            enqueue(&q, references[i]);
            faults++;
        } else {
            int top = dequeue(&q);
            for(j = 0; j < MEM_SIZE; j++) {
                if(mem[j] == top) {
                    mem[j] = references[i];
                    break;
                }
            }
            enqueue(&q, references[i]);
            faults++;
        }
    }
    return faults;
}

示例2:消息队列

消息队列是一种异步通信机制,常用于进程间通信。一个进程将消息发送到队列,另一个进程从队列中读取消息。

#define MAX_SIZE 1000

typedef struct {
    int queue[MAX_SIZE];
    int front, rear;
    pthread_mutex_t mutex;
    pthread_cond_t notEmpty, notFull;
} MsgQueue;

void initMsgQueue(MsgQueue *q) {
    q->front = q->rear = 0;
    pthread_mutex_init(&q->mutex, NULL);
    pthread_cond_init(&q->notEmpty, NULL);
    pthread_cond_init(&q->notFull, NULL);
}

void sendMsg(MsgQueue *q, int msg) {
    pthread_mutex_lock(&q->mutex);
    while(q->rear - q->front >= MAX_SIZE) {
        pthread_cond_wait(&q->notFull, &q->mutex);
    }
    q->queue[q->rear++ % MAX_SIZE] = msg;
    pthread_mutex_unlock(&q->mutex);
    pthread_cond_signal(&q->notEmpty);
}

int recvMsg(MsgQueue *q) {
    int msg;
    pthread_mutex_lock(&q->mutex);
    while(q->rear <= q->front) {
        pthread_cond_wait(&q->notEmpty, &q->mutex);
    }
    msg = q->queue[q->front++ % MAX_SIZE];
    pthread_mutex_unlock(&q->mutex);
    pthread_cond_signal(&q->notFull);
    return msg;
}

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

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • Java数据结构常见几大排序梳理

    Java数据结构常见几大排序梳理 在Java中,数据排序是非常常见的操作。下面我们详细讲解一下Java数据结构常见几大排序的梳理。 常见几大排序 Java数据结构中常见几种排序算法包括: 冒泡排序(Bubble Sort) 快速排序(Quick Sort) 插入排序(Insertion Sort) 选择排序(Selection Sort) 希尔排序(Shel…

    数据结构 2023年5月17日
    00
  • C语言数据结构实现银行模拟

    C语言数据结构实现银行模拟攻略 背景介绍 银行模拟是计算机学科中一个重要的数据结构实践练习项目。它涉及到队列(Queue)等数据结构的应用,也是计算机基础课程的一个重要组成部分。 代码实现 1. 队列的实现 首先,我们需要实现一个队列(Queue)结构体,包含 QueueSize、Front、Rear 三个成员变量: struct Queue { int Q…

    数据结构 2023年5月17日
    00
  • 深入PHP中的HashTable结构详解

    深入PHP中的HashTable结构详解 在PHP中,HashTable是一种基础数据结构,常用于存储对象的属性和方法等各种数据,本篇攻略将深入介绍HashTable的实现原理和应用。 HashTable的实现原理 HashTable并不是一种单一的数据结构,它可以根据不同的需求来采用不同的实现方式。在PHP中,我们经常使用的是基于链表的实现方式,也就是链式…

    数据结构 2023年5月17日
    00
  • C语言数据结构二叉树简单应用

    C语言数据结构二叉树简单应用攻略 1. 什么是二叉树? 二叉树(Binary Tree)是一种树形结构,它的每个节点最多包含两个子节点,它是非线性数据结构,可以用来表示许多问题,例如家族关系、计算机文件系统等等。 2. 二叉树的基本操作 二叉树的基本操作包括插入、删除、查找等等,本攻略主要讲解插入和查找的实现。 插入操作的代码如下: // 二叉树的插入操作 …

    数据结构 2023年5月17日
    00
  • C#中的数据结构介绍

    C#中的数据结构介绍 什么是数据结构? 数据结构是数据的组织、存储和管理方式。在计算机科学中,数据结构是指数据的组织形态。 C# 中常见的数据结构 在 C#中,常用的数据结构有以下几种。 1. 数组 数组是一种存储固定大小的相同类型元素的顺序集合。在 C# 中数组可以是单维、多维或交错的,并且数组支持索引和 LINQ 查询操作。在创建数组时需要指定数组的大小…

    数据结构 2023年5月17日
    00
  • Python实现的数据结构与算法之双端队列详解

    Python实现的数据结构与算法之双端队列详解 什么是双端队列? 双端队列是一种具有队列和栈的性质的数据结构,可以在队列两端进行插入和删除操作。双端队列可以实现两端的操作,因此可以在队列两端进行插入和删除操作,既可以像队列一样先进先出,也可以像栈一样后进先出。 双端队列的操作 add_front(item):在队头插入一个元素; add_rear(item)…

    数据结构 2023年5月17日
    00
  • 【ACM算法竞赛日常训练】DAY10题解与分析【月月给华华出题】【华华给月月出题】| 筛法 | 欧拉函数 | 数论

    DAY10共2题: 月月给华华出题 华华给月月出题 难度较大。 ? 作者:Eriktse? 简介:211计算机在读,现役ACM银牌选手?力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)?? 原文链接(阅读原文获得更好阅读体验):https://www.eriktse.com/algorithm/110…

    算法与数据结构 2023年4月17日
    00
  • C语言结构体struct详解

    C语言结构体struct详解 什么是结构体? 在C语言中,结构体是一种用户自定义的数据类型,它可以将不同的数据类型组合在一起形成一个新的数据类型。结构体主要由结构体名、成员和符号构成。 使用结构体可以方便地定义一些复杂的数据类型,例如表示一个学生信息的数据类型,可以包括姓名、学号、性别、年龄等信息。 结构体的定义和声明 结构体的定义通常放在函数外部,以便在整…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部