数据结构C++语言版 -- 栈和队列

大二学生的 C++数据结构 有部分Openjudge提交的代码没有删除

邮箱:liu_772021@yeah.net

欢迎交流讨论~

有用的话,点赞留言就可以表示感谢啦~



//
//  main.cpp
//  Stack and Queue
//
//  Created by Liu_77 on 2021/12/15.
//

#include <iostream>
#include <cstring>

using namespace std;

#define MAXSIZE 100
typedef int ElemType;

//栈的结构体声明
typedef struct {
    //保存栈的元素
    ElemType data[MAXSIZE];
    //栈顶指针
    int top;
}SqStack;

//队列的结构体声明
typedef struct{
    ElemType data[MAXSIZE];
    int front,rear;
}SqQueue;

//初始化栈算法:设定栈顶指针top = -1(清空栈)
void InitStack(SqStack &st){
    st.top = -1;
}

//销毁栈:系统自动释放空间
void DestroyStack(SqStack st){
    
}

//进栈算法
int Push(SqStack &st,ElemType x){
    //如果栈已满,上溢出,返回-1
    if(st.top == MAXSIZE - 1){
        return 0;
    }
    else{
        st.top++;
        st.data[st.top] = x;
        return 1;
    }
}

//出栈算法
int Pop(SqStack &st,ElemType &x){
    if(st.top == -1){
        return 0;
    }
    else{
        x = st.data[st.top];
        st.top--;
        return 1;
    }
}

//重载Pop,char型返回x
int Pop(SqStack &st,char &x){
    if(st.top == -1){
        return 0;
    }
    else{
        x = st.data[st.top];
        st.top--;
        return 1;
    }
}

//获取栈顶元素
int GetTop(SqStack st,ElemType &x){
    if(st.top == -1) return 0;
    else{
        x = st.data[st.top];
        return 1;
    }
}

//判断栈空算法
int StackEmpty(SqStack st){
    if(st.top == -1) return 1;
    else return 0;
}

//栈的链式存储结构
typedef struct node{
    //存储结点数据
    ElemType data;
    //指针域:自顶指向下。
    struct node *next;
}LinkStack;
//栈空条件:LS == NULL
//栈满条件:不考虑

//销毁栈运算算法
void DestroyStack_L(LinkStack *&ls,ElemType x){
    LinkStack *pre = ls,*p;
    if(pre == NULL) return;
    p = pre->next;
    while(p != NULL){
        free(pre);
        pre = p;
        p = p->next;
    }
    free(pre);
}

//进栈算法
int Push_L(LinkStack *&ls,ElemType x){
    LinkStack *p;
    p = (LinkStack *)malloc(sizeof(LinkStack));
    p->data = x;
    p->next = ls;
    ls = p;
    return 1;
}

//出栈算法
//ls是链栈的顶指针。
int Pop_L(LinkStack *&ls,ElemType &x){
    LinkStack *p;
    if(ls == NULL) return 0;
    else{
        p = ls;
        x = p->data;
        ls = p->next;
        free(p);
        return 1;
    }
}

//获取栈顶元素
int GetTop_L(LinkStack *ls,ElemType &x){
    if(ls == NULL) return 0;
    else{
        x = ls->data;
        return 1;
    }
}

//判断栈空
int StackEmpty_L(LinkStack *ls){
    if(ls == NULL) return 1;
    else return 0;
}

//判断进栈出栈操作是否合法;I表示进展,O表示出栈。
//str是输入的字符串;n是字符串长度。
int Judge(char str[],int n){
    int i;
    ElemType x;
    SqStack st;
    InitStack(st);
    for(i = 0;i<n;i++){
        if(str[i] == 'I'){
            Push(st,str[i]);
        }
        else if(str[i] == 'O'){
            if(!Pop(st,x)){
                DestroyStack(st);
                return 0;
            }
        }
    }
    if(StackEmpty(st)){
        DestroyStack(st);
        return 1;
    }
    else{
        DestroyStack(st);
        return 0;
    }
}

//判断字符串是否是回文字符串;n是字符串长度
int Palindrome(char str[],int n){
    SqStack st;
    InitStack(st);
    int i;
    char ch;
    //进栈所有字符
    for(i = 0;i<n;i++){
        Push(st,str[i]);
    }
    
    //从头遍历字符串,直道栈空
    i = 0;
    while(!StackEmpty(st)){
        Pop(st,ch);
        //先判断是否相等,再自加i。
        if(ch != str[i++]){
            //出现不相等的,不是回文字符串,返回0
            DestroyStack(st);
            return 0;
        }
    }
    //全部判断完毕,是回文字符串,返回1
    DestroyStack(st);
    return 1;
}

//自己写的,进栈一半判断回文
int Palindrome_2(char str[],int n){
    SqStack st;
    InitStack(st);
    int i;
    char ch;
    //进栈前面一半字符串
    //奇数个,正中间的字符无需进栈判断;偶数个则刚好需要进栈。
    for(i = 0;i<(n/2);i++){
        Push(st,str[i]);
    }
    if(n%2 == 1){
        i++;
    }
    
    //继续遍历字符串,直到栈空(字符串也恰好遍历完)
    while(!StackEmpty(st)){
        Pop(st,ch);
        //先判断是否相等,再自加i。
        if(ch != str[i++]){
            //出现不相等的,不是回文字符串,返回0
            DestroyStack(st);
            return 0;
        }
    }
    //全部判断完毕,是回文字符串,返回1
    DestroyStack(st);
    return 1;
}


//括号匹配算法
int Match(char exp[],unsigned long n){
    SqStack st;
    InitStack(st);
    int flag = 1,i = 0;
    char ch;
    
    //括号匹配部分:出现不匹配,则flag = 0,跳出循环;直到整个字符串遍历完毕
    //快速算法:出现不匹配即跳出;但不能知道哪种括号不匹配。
    /*
    while(i<n && flag == 1){
        switch(exp[i]){
            case'(':case'[':case'{':
                Push(st,exp[i]);break;
            case')':
                if(!Pop(st,ch) || ch != '(') flag = 0;break;
            case']':
                if(!Pop(st,ch) || ch != '[') flag = 0;break;
            case'}':
                if(!Pop(st,ch) || ch != '{') flag = 0;break;
        }
        i++;
    }
     */
    
    int left = 0,right = 0;
    while(i<n){
        switch(exp[i]){
            case'(':case'[':case'{':{
                left++;
                Push(st,exp[i]);
            }
                break;
            case')':{
                right++;
                if(!Pop(st,ch) || ch != '(') flag = 0;
            }
                break;
            case']':{
                right++;
                if(!Pop(st,ch) || ch != '[') flag = 0;
            }
                break;
            case'}':{
                right++;
                if(!Pop(st,ch) || ch != '{') flag = 0;
            }
                break;
        }
        i++;
    }
    
    if(left > right){
        cout<<"Extra left brackets\n";
        DestroyStack(st); return 0;
    }
    else if(left < right){
        cout<<"Extra right brackets\n";
        DestroyStack(st); return 0;
    }
    
    //如果栈空且括号匹配,返回1
    if(StackEmpty(st) && flag == 1){
        cout<<"Brackets match\n";
        DestroyStack(st); return 1;
    }
    //否则,抛出第一个多余字符,返回0
    else{
        cout<<"Brackets not match\n";
        DestroyStack(st); return 0;
    }
}

void DispStr(char *a,unsigned long length){
    printf("The list you have input: ");
    for(int i = 0;i<length;i++){
        printf("%c ",*(a+i));
    }
    printf(",\nThe Answer is:\n");
}

//利用栈,十进制转8进制:
//最后利用栈输出:利用了栈的先进后出特点,完成短除法中的 余数“倒着取”,获得正确结果。
void tenToEight(SqStack &st, int num_Ten) {
    //短除法,当最终结果还不为0,循环:
    while (num_Ten != 0) {
        //将当前数字模【8】,进栈。
        Push(st, num_Ten % 8);
        //更新当前数字:除以8取整数,继续短除。
        num_Ten /= 8;
    }
    return;
}

//-----------队列----------------
//初始化队列算法
void InitQueue(SqQueue &sq){
    sq.rear = sq.front = 0;
}

//销毁队列运算算法
void DestroyQueue(SqQueue sq){
    
}

//进队运算算法
int EnQueue(SqQueue &sq,ElemType x){
    //队满上溢出:队尾+1对最大长度取余,如果等于队首的标记,则相当于“追尾”,队伍满了
    if((sq.rear+1)%MAXSIZE == sq.front){
        return 0;
    }
    //若不满,【循环】进1.
    sq.rear = (sq.rear+1)%MAXSIZE;
    sq.data[sq.rear] = x;
    return 1;
}

//出队运算算法
int DeQueue(SqQueue &sq,ElemType &x){
    //队空下溢出
    if(sq.rear == sq.front){
        return 0;
    }
    //队头循环进1,出队
    sq.front = (sq.front+1)%MAXSIZE;
    x = sq.data[sq.front];
    return 1;
}

//取队头元素算法
int GetHead(SqQueue sq,ElemType &x){
    //队空下溢出
    if(sq.rear == sq.front){
        return 0;
    }
    //将队列头指针前一个位置的元素赋给x
    x = sq.data[(sq.front+1)%MAXSIZE];
    return 1;
}

int QueueEmpty(SqQueue sq){
    if(sq.rear == sq.front) return 1;
    else return 0;
}

//----------队列的链式存储结构-------------------
//链队中的数据结点的类型声明:
typedef struct QNode{
    //存放队中元素
    ElemType data;
    //指向下一个结点的指针
    struct QNode *next;
}QType;

//链队结点声明:
typedef struct qptr{
    //队头指针
    QType *front;
    //队尾指针
    QType *rear;
}LinkQueue;
//实际上是带有对头指针和队尾指针的【单链表】,队尾指针指向队尾结点即最后一个结点
//队头结点和队尾结点结合起来构成链队结点

//队空条件:lq->front == NULL
//堆满条件:不考虑
//进队操作:创建结点p,将其插入队尾(尾插法),并由lq->rear指向它。
//出队操作:删除队头结点

//初始化队列运算:
void InitQueue(LinkQueue *&lq){
    lq = (LinkQueue *)malloc(sizeof(LinkQueue));
    lq->rear = lq->front = NULL;
}

//销毁队列运算算法
void DestroyQueue(LinkQueue *&lq){
    QType *pre = lq->front,*p;
    //非空队列情况
    if(pre != NULL){
        //只有一个数据结点情况
        if(pre == lq->rear){
            //释放pre结点
            free(pre);
        }
        //有两个及以上结点情况:
        else{
            //pre->next不为空:
            p = pre->next;
            //直到pre后面的队空,循环暂停
            while(p != NULL){
                free(pre);
                //pre、p同步后移
                pre = p;
                p = p->next;
            }
            free(pre);
        }
    }
    //释放链队结点
    free(lq);
}

//进队运算算法
int EnQueue(LinkQueue *&lq,ElemType x){
    QType *s;
    //创建新结点s,插入到链队队尾
    s = (QType *)malloc(sizeof(QType));
    s->data = x;
    s->next = NULL;
    //原队尚为空队,front和rear均指向s结点;
    if(lq->front == NULL){
        lq->rear = lq->front = s;
    }
    //原队不为空:
    else{
        //将s结点链接到队尾
        lq->rear->next = s;
        //更新队尾指针rear指向s
        lq->rear = s;
    }
    return 1;
}

int DeQueue(LinkQueue *&lq,ElemType x){
    QType *p;
    if(lq->front == NULL){
        return 0;
    }
    //p指向队头结点;
    p = lq->front;
    //取队头元素值
    x = p->data;
    //链队只剩有一个结点
    if(lq->rear == lq->front){
        //出队该结点后,队列变空
        lq->rear = lq->front = NULL;
    }
    //链队有两个及以上结点
    else{
        //出队该结点,lq指向该结点后链结点(更新front域)
        lq->front = lq->front->next;
    }
    free(p);
    return 1;
}

//取队头元素运算算法
int GetHeaf(LinkQueue *lq,ElemType &x){
    //队空,返回0
    if(lq->front == NULL){
        return 0;
    }
    //队不空引用型变量传回x,返回1
    x = lq->front->data;
    return 1;
}

//判断队空运算算法
int QueueEmpty(LinkQueue *lq){
    if(lq->front == NULL){
        return 1;
    }
    else return 0;
}

//=----------用循环单链表表示链队-----------
typedef struct CycNode{
    ElemType data;
    struct CycNode *next;
}Qnode;
//循环单链表不带头结点,lq始终指向尾结点,lq->next为队头结点。lq == NULL时队列为空,lq->next表示只有一个结点

//初始化队列
void InitQueue(QNode *&lq){
    lq = NULL;
}

//销毁队列
void DesTroyQueue(QNode *&lq){
    QNode *pre,*p;
    if(lq != NULL){
        //当原队只有一个结点
        if(lq->next == lq){
            free(lq);
        }
        //原队中有两个以上结点
        else{
            pre = lq;
            p = pre->next;
            while(p != lq){
                //释放、pre、p同步后移
                free(pre);
                pre = p;
                p = p->next;
            }
            //释放最后一个结点
            free(pre);
        }
    }
}

//进队运算算法
void EnQueue(QNode *&lq,ElemType x){
    QNode *s;
    s = (QNode *)malloc(sizeof(QNode));
    s->data = x;
    //原队为空
    if(lq == NULL){
        lq = s;
        lq->next = lq;
    }
    //原队不空,结点s插到队尾,lq指向它
    else{
        //赋新结点指针域:指向头结点,即lq->next
        s->next = lq->next;
        //将s插入队尾,即令尾结点的指针域指向s
        lq->next = s;
        //更新尾结点为s
        lq = s;
    }
}

//出队运算算法
int DeQueue(QNode *&lq,ElemType x){
    QNode *s;
    if(lq == NULL) return 0;
    if(lq->next == lq){
        x = lq->data;
        free(lq);
        lq = NULL;
    }
    else{
        s = lq->next;
        x = s->data;
        lq->next = s->next;
        free(s);
    }
    return 1;
}

//取队头元素运算算法
int GetHead(QNode *lq,ElemType x){
    if(lq == NULL){
        return 0;
    }
    x = lq->next->data;
    return 1;
}

//判断队空运算算法
int QueueEmpty(QNode *lq){
    if(lq == NULL) return 1;
    else return 0;
}

//队列的应用示例
//输出队中所有元素
int DispAllQueue(QNode *lq){
    QNode *p;
    if(QueueEmpty(lq)){
        return 0;
    }
    else{
        p = lq->next;
        while(p != lq){
            printf("%d ",p->data);
            p = p->next;
        }
        printf("%d\n",lq->data);
    }
    return 1;
}

int main(int argc, const char * argv[]) {
    string s;
    cin >> s;
    
    unsigned long length = s.length();
    char *a = (char *)malloc(sizeof(char)*length);
    strcpy(a, s.c_str());
    cout<<"length = "<<length<<endl;
    DispStr(a, length);
    Match(a,length);
    return 0;
}

就可以表示感谢啦

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值