栈与队列

栈与队列都是数据结构的一种,只能在端口进行增删数据操作
栈的特点的先入后出
队列的特点的先入先出

简单的栈(数组栈和链栈)

//1. 数组栈
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MaxIndex 100
typedef struct{
    char data[MaxIndex];
    int top;
}Stack;
//初始化数组栈
Stack *init(){
    Stack *p = (Stack*)malloc(sizeof(Stack));
    if(p == NULL)
        return 0;
    p->top=0;
    return p;
}
//入栈
void push(Stack *p, char ch){
    if(p->top >= MaxIndex){
        printf("Overflow!\n");
        return;
    }
    p->data[p->top] = ch;
    p->top++;
}
//出栈
char pop(Stack *p){
    if(p->top <= 0){
        printf("Underflow!\n");
        return NULL;
    }
    p->top--;
    return p->data[p->top];
}
//栈满
bool isFull(Stack *p){
    return p->top >= MaxIndex;
}
//栈空
bool isEmpty(Stack *p){
    return p->top == 0;
}
//遍历打印栈元素
void printStack(Stack *p){
    int index = p->top;
    while(p->top--){
        printf("%c", p->data[p->top]);
        if(p->top){
            printf(" ");
        }else{
            printf("\n");
        }
    }
    p->top = index;
}
//2.链栈
#include<stdio.h>
#include<stdlib.h>
#define MaxIndex 100
typedef struct forename{
	char data;
	struct forename* next;
}Stack;

//初始化链栈 
void init(Stack* p){ 
	p->next=NULL;
}
//入栈 
void push(Stack *p, char ch){
	Stack *temp = (Stack*)malloc(sizeof(Stack));
	temp->data = ch;
	temp->next = p->next;
	p->next = temp;
}
//出栈 
char pop(Stack *p){
	if(p->next == NULL){
		printf("Underflow!\n");
		return NULL;
	}
	Stack *temp = p->next;
	char ch = temp->data;
	p->next = temp->next;
	free(temp);
	return ch;
}
//栈空
bool isEmpty(Stack *p){
	return p->next == NULL;
}
//遍历打印栈元素 
void printStack(Stack *p){
	Stack *temp = p;
	while(temp->next != NULL){
		printf("%c", temp->next->data);
		temp = temp->next;
		if(temp->next != NULL){
			printf(" ");
		}
	}
	printf("\n");
}

使用栈可以完成一写些比较复杂的操作,例如括号的匹配、算式格式转换(前缀、中缀、后缀之间的转换)
这里以数组栈为例,用链栈也是相同的

括号匹配完整代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MaxIndex 100
typedef struct{
    char data[MaxIndex];
    int top;
}Stack;
//初始化数组栈
Stack *init(){
    Stack *p = (Stack*)malloc(sizeof(Stack));
    if(p == NULL)
        return 0;
    p->top=0;
    return p;
}
//入栈
void push(Stack *p, char ch){
    if(p->top >= MaxIndex){
        printf("Overflow!\n");
        return;
    }
    p->data[p->top] = ch;
    p->top++;
}
//出栈
char pop(Stack *p){
    if(p->top <= 0){
        printf("Underflow!\n");
        return NULL;
    }
    p->top--;
    return p->data[p->top];
}
//栈满
bool isFull(Stack *p){
    return p->top >= MaxIndex;
}
//栈空
bool isEmpty(Stack *p){
    return p->top == 0;
}
//遍历打印栈元素
void printStack(Stack *p){
    int index = p->top;
    while(p->top--){
        printf("%c", p->data[p->top]);
        if(p->top){
            printf(" ");
        }else{
            printf("\n");
        }
    }
    p->top = index;
}
//括号匹配
bool bracketsMatch(char brackets[]){
    Stack *stack = init();
    int n = strlen(brackets);
    if(n%2){
        return false;
    }
    for(int i=0; i<n; i++){
        if(brackets[i] == '(' || brackets[i] == '{' || brackets[i] == '['){
            push(stack, brackets[i]);
        }else{
            if(isEmpty(stack)){
                return false;
            }
            char ch = pop(stack);
            if(ch == '(' && brackets[i] != ')'){
                return false;
            }
            if(ch == '[' && brackets[i] != ']'){
                return false;
            }
            if(ch == '{' && brackets[i] != '}'){
                return false;
            }
        }
    }
    return true;
}
int main(){
    char str[20];
    scanf("%s", str);
    printf("Brackets match? %s", bracketsMatch(str) ? "true" : "false");
    return 0;
}

 表达式转换,这里只展示后缀表达式转中缀表达式,剩下两个都很简单。
 后缀转中缀主要思路的是栈与二叉树相结合,遍历字符串,为数字则建树入栈,为运算符则建树,出栈两次,分别加为该树的左右子节点,再将此新树入栈,待遍历完成字符串,出栈,中序遍历该树,同时加括号。
 注意,加括号的规则是:1. 根节点为乘除,子节点为加减,子节点的两个子节点两侧加括号 2. 根节点为减,右节点为加减,右节点的两个子节点两侧加括号

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MaxIndex 100
//二叉树
typedef struct TreeNode
{
    char val;
    struct TreeNode *left;
    struct TreeNode *right;
} BiNode, *BiTree;
typedef struct
{
    BiTree data[MaxIndex];
    int top;
} Stack;
//初始化数组栈
Stack *init()
{
    Stack *p = (Stack *)malloc(sizeof(Stack));
    if (p == NULL)
        return 0;
    p->top = 0;
    return p;
}
//入栈
void push(Stack *p, BiTree root)
{
    if (p->top >= MaxIndex)
    {
        printf("Overflow!\n");
        return;
    }
    p->data[p->top] = root;
    p->top++;
}
//出栈
BiTree pop(Stack *p)
{
    if (p->top <= 0)
    {
        printf("Underflow!\n");
        return NULL;
    }
    p->top--;
    return p->data[p->top];
}
//栈空
bool isEmpty(Stack *p)
{
    return p->top == 0;
}
//二叉树创建
BiTree treeInit(char value)
{
    BiTree root = (BiTree)malloc(sizeof(BiTree));
    root->val = value;
    root->left = NULL;
    root->right = NULL;
    return root;
}
//二叉树增加左节点
void addLeft(BiTree root, BiTree lnode)
{
    if (root->left != NULL)
    {
        addLeft(root->left, lnode);
    }
    else
    {
        root->left = lnode;
    }
}
//二叉树增加右节点
void addRight(BiTree root, BiTree rnode)
{
    if (root->right != NULL)
    {
        addRight(root->right, rnode);
    }
    else
    {
        root->right = rnode;
    }
}
//二叉树中序递归遍历(先左后右)
//加括号的规则是:1. 根节点为乘除,子节点为加减,子节点加括号 2. 根节点为减,右节点为加减,右节点加括号
void inOrder(BiTree root)
{
    if (root == NULL)
    {
        return;
    }
    if ((root->val == '*' || root->val == '/') && (root->left->val == '+' || root->left->val == '-'))
    {
        printf("(");
        inOrder(root->left);
        printf(")");
    }
    else
    {
        inOrder(root->left);
    }

    printf("%c", root->val);

    if (((root->val == '*' || root->val == '/') && (root->right->val == '+' || root->right->val == '-')) || root->val == '-' && (root->right->val == '-' || root->right->val == '+'))
    {
        printf("(");
        inOrder(root->right);
        printf(")");
    }
    else
    {
        inOrder(root->right);
    }
}
//后缀表达式转中缀表达式(假定后缀表达式无括号)
void change(char exp[])
{
    Stack *stack = init();
    int n = strlen(exp);
    for (int i = 0; i < n; i++)
    {
        if (exp[i] >= '0' && exp[i] <= '9')
        {
            push(stack, treeInit(exp[i]));
        }
        else
        {
            if (isEmpty(stack))
            {
                printf("Wrong!\n");
                return;
            }
            BiTree c1, c2, c3;
            c1 = pop(stack);
            if (isEmpty(stack))
            {
                printf("Wrong!\n");
                return;
            }
            c2 = pop(stack);
            c3 = treeInit(exp[i]);
            addLeft(c3, c2);
            addRight(c3, c1);
            push(stack, c3);
        }
    }
    inOrder(pop(stack));
    return;
}
int main()
{
    char str[20];
    scanf("%s", str);
    change(str);
    return 0;
}

队列

普通队列与栈相似,普通数组队列存在假溢出现象,链队列则不存在队满情况

链队列

#include<stdio.h>
#include<stdlib.h>
//链队列
typedef struct node {
    char data;
    node* next;
}QueueNode;
typedef struct queue {
    QueueNode* front;
    QueueNode* rear;
}Queue;
//初始化
Queue* init(){
    Queue* que = (Queue*)malloc(sizeof(Queue));
    que->front = (QueueNode*)malloc(sizeof(QueueNode));
    que->rear = que->front;
    que->front->next = NULL;
    return que;
}
//队空
bool queueIsEmpty(Queue* que){
    if(que->front == que->rear){
        return true;
    }
    return false;
}
//入队
void enQueue(Queue* que, char ch){
    QueueNode* p = (QueueNode*)malloc(sizeof(QueueNode));
    p->data = ch;
    p->next = NULL;
    que->rear->next = p;
    que->rear = p;
}
//出队
char outQueue(Queue* que){
    QueueNode* p = que->front;
    if(queueIsEmpty(que)){
        return NULL;
    }
    char outch = p->next->data;
    que->front = que->front->next;
    free(p);
    return outch; 
}
//遍历打印
void printQueue(Queue* que){
    QueueNode *p = que->front;
    if(queueIsEmpty(que)){
        printf("The queue is empty!");
        return;
    }
    while((p = p->next) && p != que->rear->next){
        printf("%c", p->data);
    }
    printf("\n");
    return;
}
//测试样例7.
int main(){
    Queue* myQueue = init();
    printf("%s", queueIsEmpty(myQueue) ? "Queue is empty\n" : "Queue is not empty\n");
    enQueue(myQueue, 'M');
    enQueue(myQueue, 'y');
    enQueue(myQueue, ' ');
    enQueue(myQueue, 'q');
    enQueue(myQueue, 'u');
    enQueue(myQueue, 'e');
    enQueue(myQueue, 'u');
    enQueue(myQueue, 'e');
    enQueue(myQueue, ' ');
    enQueue(myQueue, 'i');
    enQueue(myQueue, 's');
    enQueue(myQueue, ' ');
    enQueue(myQueue, 'c');
    enQueue(myQueue, 'r');
    enQueue(myQueue, 'a');
    enQueue(myQueue, 'z');
    enQueue(myQueue, 'y');
    enQueue(myQueue, '!');
    printQueue(myQueue);
    for(int i = 0; i < 3; i++){
        outQueue(myQueue);
    }
    printQueue(myQueue);
}

循环队列

#include<stdio.h>
#include<stdlib.h>
#define MAXNUM 100
//循环队列
typedef struct queue {
    char data[MAXNUM];
    int front, rear, length;
}loopQueue;
//初始化
void init(loopQueue* que){
    que->front = 0;
    que->rear = 0;
    que->length = 0;
}
//队空
bool isEmpty(loopQueue* que){
    if(que->length == 0){
        return true;
    }
    return false;
}
//队满
bool isFul(loopQueue* que){
    if (que->length == MAXNUM)
    {
        return true;
    }
    return false;
}
//队列长度
int queueLength(loopQueue* que){
    return que->length;
}
//入队
void enQueue(loopQueue* que, char ch){
    if(isFul(que)){
        printf("The queue is full!\n");
        return;
    }
    que->data[que->rear] = ch;
    que->length++;
    que->rear = (que->rear + 1) % MAXNUM;
}
//出队
char outQueue(loopQueue* que){
    if (isEmpty(que))
    {
        printf("The queue is empty!\n");
        return NULL;
    }
    char outch = que->data[que->front];
    que->length--;
    que->front = (que->front + 1) % MAXNUM;
    return outch;
}
//遍历打印
void printQueue(loopQueue* que){
    for(int i = 0; i < que->length; i++){
        int x = (que->front + i)%MAXNUM;
        printf("%c", que->data[x]);
    }
    printf("\n");
}
//测试样例
int main(){
    loopQueue* myQueue;
    init(myQueue);
    printf("%s", isEmpty(myQueue) ? "Queue is empty\n" : "Queue is not empty\n");
    enQueue(myQueue, 'M');
    enQueue(myQueue, 'y');
    enQueue(myQueue, ' ');
    enQueue(myQueue, 'q');
    enQueue(myQueue, 'u');
    enQueue(myQueue, 'e');
    enQueue(myQueue, 'u');
    enQueue(myQueue, 'e');
    enQueue(myQueue, ' ');
    enQueue(myQueue, 'i');
    enQueue(myQueue, 's');
    enQueue(myQueue, ' ');
    enQueue(myQueue, 'h');
    enQueue(myQueue, 'a');
    enQueue(myQueue, 'p');
    enQueue(myQueue, 'p');
    enQueue(myQueue, 'y');
    enQueue(myQueue, '!');
    printQueue(myQueue);
    for (int i = 0; i < 3; i++)
    {
        outQueue(myQueue);
    }
    printQueue(myQueue);
}

至于队列应用举例,可以参考这篇博客:队列的应用

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值