数据结构-栈和队列

caoy19/Data_Structure: definition and application of classic structure, like stack, queue, tree, gragh and so on. This repo applies to some freshers and testers for 考研. (github.com)icon-default.png?t=N6B9https://github.com/caoy19/Data_Structure

目录

顺序栈

单链栈

双链栈 

测试上述栈结构 

栈应用-括号匹配

队列 

循环队列(数组)

链表队列(链表)

测试上述队列结构

顺序栈

//顺序栈,用数组存储的栈。
/*
标准:
1.定义加基本操作,判空,判满,进栈,出栈。
2.top指针(伪指针,就是一个int变量)一般有俩种,一个指向栈顶元素,初始化为-1(本次使用这个)
一个指向栈顶元素的下一个位置,初始化为0.
*/
#include<stdio.h>
#include<malloc.h>
#define maxSize 50
typedef struct{
    int value;
}ElemType;
//一般ElemType就是int,直接写就行,这是用户所操作的最底层,其他均封装起来
typedef struct{
    ElemType data[maxSize];
    int top;//栈顶指针指向栈顶元素
}Stack;
bool InitStack(Stack &s){
    s.top=-1;
    return true;
}
bool StackEmpty(Stack s){
    return s.top==-1;
}
bool StackFull(Stack s){
    return s.top==maxSize-1;
}
bool push(Stack &s,ElemType x){
    if(StackFull(s)) return false;
    s.data[++s.top]=x;
    return true;
}
bool pop(Stack &s,ElemType &x){ //&x是为了x接受输出
    if(StackEmpty(s)) return false;
    x=s.data[s.top--];
    return true;
}

单链栈

//单链栈。
/*
标准:
1.定义加基本操作,判空,进栈,出栈。
2.栈顶在链头,入栈出栈均在链头。
3.采用带头结点单链表,故不需要再来一个top指针了。
*/
#include<stdio.h>
#include<malloc.h>
typedef struct{
    int value;
}ElemType;
//一般ElemType就是int,直接写就行,这是用户所操作的最底层,其他均封装起来
typedef struct SNode{
    ElemType data;
    SNode *next;
}SNode,*Stack; //这个就是简洁表示,要是更规范点可以再定义个Stack结构体。
bool InitStack(Stack &s){
    SNode *p=(SNode*)malloc(sizeof(SNode));//头结点
    p->next=NULL;
    s=p; 
    return true;
}
bool StackEmpty(Stack s){
    return s->next==NULL;
}
bool push(Stack &s,ElemType x){
    SNode *p=(SNode *)malloc(sizeof(SNode));//插入结点
    p->data=x;
    p->next=s->next;
    s->next=p;
    return true;
}
bool pop(Stack &s,ElemType &x){ //&x是为了x接受输出
    if(StackEmpty(s)) return false;
    SNode *p=s->next;
    x=p->data;
    s->next=p->next;
    free(p);
    return true;
}

双链栈 

//双向链栈
/*
标准:
1.定义加基本操作,判空,进栈,出栈。
2.栈顶在链尾,需要维持一个top指针指向链尾。
3.采用带头结点双链表。
*/
#include<stdio.h>
#include<malloc.h>
typedef struct{
    int value;
}ElemType;
//一般ElemType就是int,直接写就行,这是用户所操作的最底层,其他均封装起来
typedef struct SNode{
    ElemType data;
    SNode *pior,*next;
}SNode; 
//规范表示,重新定义个结构体Stack:
typedef struct {
    SNode *head,*top;//head头结点,top栈顶在链尾
}*Stack;
bool InitStack(Stack &s){
    s=(Stack)malloc(sizeof(Stack));//分配栈空间
    SNode *p=(SNode*)malloc(sizeof(SNode));//分配头结点空间
    p->pior=NULL;//头结点赋值
    p->next=NULL;//头结点赋值
    s->head=p;
    s->top=p;
    return true;
}
bool StackEmpty(Stack s){
    return s->head==s->top;
}
bool push(Stack &s,ElemType x){
    SNode *p=(SNode *)malloc(sizeof(SNode));//插入结点
    p->data=x;
    p->next=NULL;
    p->pior=s->top;
    s->top->next=p;//这句别忘了,仔细点
    s->top=p;
    return true;
}
bool pop(Stack &s,ElemType &x){ //&x是为了x接受输出
    if(StackEmpty(s)) return false;
    SNode *p=s->top;
    x=p->data;
    s->top=s->top->pior;
    s->top->next=NULL;
    free(p);
    return true;
}

测试上述栈结构 

#include<stdio.h>
#include<malloc.h>
//#include "_1SequenceStack.h"//test1
//#include "_2SingleListStack.h"//test2
#include "_3DoubleDirListStack.h"//test3

//test,实际考试就这么写,定义Stack,init,然后就可以用几个方法
//StackEmpty,StackFull,Push,Pop,GetTop
//可见单链栈和顺序栈的测试一模一样,这是因为封装了具体实现,
//在做数据结构大题的时候,也不用管是怎么样实现的,只用使用即可。
int main(){
    Stack s;
    InitStack(s);
    if (StackEmpty(s)) printf("empty\n");
    else  printf("not empty");
    for (int i = 0; i < 100; i++)
    {
        ElemType a;
        a.value=i;
        if(push(s,a)) printf("%d 进栈成功\n",a.value);
        else  printf("%d 进栈失败\n",a.value);
       
    }
    for (int i = 0; i < 6; i++)
    {
        ElemType a;
        if(pop(s,a)) printf("%d出栈\n",a.value);
        else  printf("出栈失败");
    }  
}

栈应用-括号匹配

//括号匹配
/*
1.从左往右遍历表达式中括号元素:
若当前括号元素是左括号则将其入栈
若当前括号元素是右括号,则弹出栈顶元素,与当前元素匹配。
若匹配则继续遍历,若不匹配则字符串匹配失败
2.遍历完成后,若栈空则匹配成功,若栈非空则匹配失败
*/
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include "_1SequenceStack.h"
bool Match(char *s){
    Stack signStack;//
    InitStack(signStack);
    for (int i = 0; i < strlen(s); i++){
        //考试时候不用写这俩步,这地方写是因为为了运行,就是因为栈实现写的还不够完美(要支持泛型)
        ElemType elem;
        elem.value=s[i];
        //考试直接从这开始
        if(s[i]=='(' || s[i]=='[') push(signStack,elem);
        if(s[i]==')'){
            pop(signStack,elem);
            if (elem.value!='(') return false; 
        }
        if(s[i]==']'){
            pop(signStack,elem);
            if (elem.value!='[') return false; 
        }
    }
    if (StackEmpty(signStack)) return true;
    return false;
}

int main(){
    char s[50]="(2+3)*4-[5*(2-3)]*2";
    //scanf("%s",s);//给出字符串
    if(Match(s)) printf("匹配成功"); 
    else printf("匹配失败"); 
}

队列 

循环队列(数组)

//循环队列,用数组实现。
/*
标准:
1.入队操作在队尾进行,只改变rear。出队操作在队头进行,只改变front。
2.front,rear指向各个教材都不太一样,大致有三种情况
front=0,rear=0 front指向队头元素,rear指向队尾元素的下一个位置(常见)==》本次的定义
front=-1,rear=-1 front指向队头元素的前一个位置,rear指向队尾元素(常见)
front=0, rear=-1 front指向队头元素,rear指向队尾元素(是因为判断不像前面俩个那么简单,稍微复杂点)
3.解决循环队列的队空队满判断,共有三种办法
空出一个位置,常用。==》本次使用这个
增加size标志,easy
增加tag标志,每次入队tag=1,只会队满,每次出队tag=0,只会队空
*/
#include<stdio.h>
#include<malloc.h>
#define maxSize 5
typedef struct{
    int value;
}ElemType;
typedef struct {
    ElemType data[maxSize];
    int front,rear;
}Queue;
bool InitQueue(Queue &q){
    q.front=0;//指向对头元素
    q.rear=0;//指向队尾元素的下一个位置
    return true;
}
bool QueueEmpty(Queue q){
    return q.front==q.rear;
}
bool QueueFull(Queue q){
    return (q.rear+1)%maxSize==q.front;
}
int QueueLength(Queue q){
    return (q.rear+maxSize-q.front)%maxSize;
}
bool EnQueue(Queue &q,ElemType x){
    if (QueueFull(q)) return false;
    q.data[q.rear]=x;
    q.rear=(q.rear+1)%maxSize;//只改变rear
    return true;
}
bool DeQueue(Queue &q,ElemType &x){
    if (QueueEmpty(q)) return false;
    x=q.data[q.front];
    q.front=(q.front+1)%maxSize;
    return true;
}

链表队列(链表)

//用单链表实现的队列
/*
标准:
1.入队在链尾,需要维持一个队尾指针。
2.出队在链头,使用带头结点的单链表,自动有一个队头指针。
总结:头删尾插。
*/
#include<stdio.h>
#include<malloc.h>
typedef struct{
    int value;
}ElemType;
//一般ElemType就是int,直接写就行,这是用户所操作的最底层,其他均封装起来
typedef struct QNode{
    ElemType data;
    QNode *next;
}QNode;
typedef struct {
    QNode *head,*rear;//head指向头结点,rear队尾指针。
}*Queue;
bool InitQueue(Queue &q){
    QNode *p=(QNode *)malloc(sizeof(QNode));
    p->next=NULL;
    q=(Queue)malloc(sizeof(Queue));
    q->head=p;
    q->rear=p;
    return true;
}
bool QueueEmpty(Queue q){
    return q->head==q->rear;
}
bool EnQueue(Queue &q,ElemType x){
    QNode *p=(QNode*)malloc(sizeof(QNode));
    p->data=x;
    p->next=NULL;
    q->rear->next=p;
    q->rear=p;
    return true;
}
bool DeQueue(Queue &q,ElemType &x){
    if (QueueEmpty(q)) return false;
    QNode *p=q->head->next;
    x=p->data;
    q->head->next=p->next;
    if(q->rear==p) q->rear=q->head;//这句话容易忘,如果只有一个元素记得改rear。
    free(p);
    return true;
}

测试上述队列结构

#include<stdio.h>
#include<malloc.h>
//#include "_5CircleQueue.h"
#include "_6ListQueue.h"
int main(){
    Queue q;
    InitQueue(q);
    for (int i = 0; i < 10; i++)
    {
        ElemType x;
        x.value=i;
        if (EnQueue(q,x)) printf("%d入队成功\n",x.value);
        else printf("%d入队失败\n",x.value);
    }
    for (int i = 0; i < 10; i++)
    {
        ElemType x;
        if (DeQueue(q,x)) printf("%d出队成功\n",x.value);
        else printf("%d出队失败\n",x.value);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值