第六周实验(数据结构)

本文展示了如何使用循环队列实现杨辉三角的打印,以及栈在括号匹配、判断序列是否为栈的输出序列、字符串镜像检查和找最长等值子串等问题中的应用。代码示例包括循环队列的实现和栈的各种操作,强调了栈在处理逆序、匹配和查找模式等方面的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 杨辉三角

【问题描述】参考教材P103例3.6,完成杨辉三角形的打印,请用循环队列实现(利用之前已实现的循环队列数据结构的代码)。不采用“循环队列”,不给分。

【输出要求】用 cout << setw(3) << x 这样来使每个数据输出都占3列;需包含<iomanip>

【样例输入】

4

【样例输出】

1

1 1

1 2 1

1 3 3 1

#include<iostream>
#include<iomanip>
using namespace std;
#define FALSE 0
#define TRUE 1
#define MAXSIZE 73
typedef int ElemType;
typedef struct{
    ElemType elem[MAXSIZE];
    int front;
    int rear;
}SeqQueue;

void InitQueue(SeqQueue *q){
    q->front=q->rear=0;
}

int EnterQueue(SeqQueue *q,ElemType x){
    if((q->rear+1)%MAXSIZE==q->front)
        return FALSE;
    q->elem[q->rear]=x;
    q->rear=(q->rear+1)%MAXSIZE;
}

int DeleteQueue(SeqQueue *q,ElemType *x){
    if(q->front==q->rear)
        return FALSE;
    *x=q->elem[q->front];
    q->front=(q->front+1)%MAXSIZE;
    return TRUE;
}
/*取队头元素并不会使队头指针后移*/
int GetHead(SeqQueue *q,int *x){
    if(q->front==q->rear)
        return FALSE;
    *x=q->elem[q->front];
    return TRUE;
}

int IsEmpty(SeqQueue *q){
    if(q->front==q->rear)
        return     TRUE;
    else 
        return FALSE;
}

void YangHuiTriangle(int N){
    SeqQueue Q;
    int n,i,temp,x;
    InitQueue(&Q);
    EnterQueue(&Q,1);                /*第一行元素入队*/
    for(n=2;n<=N;n++){               /*产生第n行元素并入队,同时打印第n-1行元素*/
        EnterQueue(&Q,1);            /*第n行第1个元素入队*/
        /*for(i=N;i>=n;i--)
            cout<<' ';
        //打印金字塔形状*/
        for(i=1;i<=n-2;i++){          /*利用队中第n-1行元素产生第n行的中间n-2个元素并入队*/
            DeleteQueue(&Q,&temp);    /*temp暂存出队元素*/
            cout<<setw(3)<<temp;          /*打印第n-1行元素*/
            GetHead(&Q,&x);
            temp=temp+x;              /*利用第n-1行元素产生第n行元素*/
            EnterQueue(&Q,temp);      /*第n行元素入队*/
        }
        DeleteQueue(&Q,&x);           /*第n-1行元素还有最后一个元素,使其出队*/
        cout<<setw(3)<<x;                 /*打印n-1行元素最后一个元素*/
        cout<<endl;
        EnterQueue(&Q,1);             /*第n行最后一个元素入队*/
    }
    while(!IsEmpty(&Q)){              /*打印最后一行元素*/
        DeleteQueue(&Q,&x);
        cout<<setw(3)<<x;
    }
}

int main(){
    int N;
    cin>>N;
    YangHuiTriangle(N);
    return 0;
}
  1. 队列元素逆置

【问题描述】已知Q是一个非空队列,S是一个空栈。仅使用少量工作变量以及对队列和栈的基本操作,编写一个算法,将队列Q中的所有元素逆置。需采用链式队列与栈(顺序或链式),否则不能得分。

【输入形式】输入的第一行为队列元素个数,第二行为队列从首至尾的元素

【输出形式】输出队列的逆置

【样例输入】

3

1 2 3

【样例输出】

3 2 1

#include<bits/stdc++.h>
using namespace std;
#define MAXSIZE 50
#define FALSE 0
#define TRUE 1
typedef  int ElemType;
typedef struct{
    ElemType elem[MAXSIZE];
    int front;
    int rear;
}SeqQueue;

typedef struct{
    ElemType elem[MAXSIZE];
    int top;
}SeqStack;

void InitQueue(SeqQueue *Q){
    Q->front=Q->rear=0;
}

int QPush(SeqQueue *Q,ElemType e){
    if((Q->rear+1)%MAXSIZE==Q->front)
        return FALSE;
    Q->elem[Q->rear]=e;
    Q->rear=(Q->rear+1)%MAXSIZE;
    return TRUE;
}

ElemType QPop(SeqQueue *Q,ElemType *x){
    if(Q->front==Q->rear)
        return FALSE;
    *x=Q->elem[Q->front];
    Q->front=(Q->front+1)%MAXSIZE;
    return *x;
}

void InitStack(SeqStack *s){
    s->top=-1;
}

int SPush(SeqStack *s,ElemType e){
    if(s->top==MAXSIZE-1)
        return FALSE;
    s->top++;
    s->elem[s->top]=e;
    return TRUE;
}

int SPop(SeqStack *s,ElemType *x){
    if(s->top==-1)
        return FALSE;
    *x=s->elem[s->top];
    s->top--;
    return TRUE;
}

int ReserveQueue(SeqQueue *Q){
    SeqStack *s;
    ElemType x;
    InitStack(s);
    while(Q->front!=Q->rear){
        QPop(Q,&x);
        SPush(s,x);
    }
    while(s->top!=-1){
        SPop(s,&x);
        QPush(Q,x);
    }
    return TRUE;
}

int main(){
    SeqQueue q;
    ElemType num;
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>num;
        QPush(&q,num);
    }
    ReserveQueue(&q);
    while(q.front!=q.rear){
        cout<<q.elem[q.front]<<' ';
    }
    return 0; 
}
  1. 括号匹配问题

【问题描述】用前面程序实现的char型链栈,解决括号匹配问题

【输入形式】以#为结束符的一个符号序列

【输出形式】如果所有的左右括号全部匹配,输出1;否则输出0

【样例输入】{([])}()#

【样例输出】1

/*输出0有两种情况:①左括号都匹配完了,而右括号多余
                   ②左括号还没有匹配完,但是左括号和右括号不匹配
                   ③左括号多余右括号,最后栈不为空,左括号剩余*/

#include<bits/stdc++.h>
using namespace std;
#define MAXSIZE 50
#define FALSE 0
#define TRUE 1
typedef char ElemType;
typedef struct{
    ElemType str[MAXSIZE];
    int top;
}SeqStack;

void InitStack(SeqStack *s){
    s->top=-1;
}

int Push(SeqStack *s,ElemType e){
    if(s->top==MAXSIZE-1)
        return FALSE;
    s->top++;
    s->str[s->top]=e;
    
    return TRUE;    
}

int Pop(SeqStack *s,ElemType *x){
    if(s->top==-1)
        return FALSE;
    *x=s->str[s->top];                  /*用指针将栈顶元素带出*/
    s->top--;
    return TRUE;
}

int GetTop(SeqStack *s,ElemType *x){    /*PS:读取栈顶元素和栈顶元素出栈不同*/   
    if(s->top==-1)
        return FALSE;
    *x=s->str[s->top];
    return TRUE;
}

int Match(char ch,char str){
    if(ch=='('&&str==')')
        return TRUE;
    else if(ch=='['&&str==']')
        return TRUE;
    else if(ch=='{'&&str=='}')
        return TRUE;
    else
        return FALSE;
}

void BracketMatch(char *str){
    SeqStack s;
    InitStack(&s);
    int i;
    char ch;
    for(i=0;str[i]!='\0';i++){
        switch(str[i]){
        case '(':
        case '[':
        case '{':
            Push(&s,str[i]);            /*左括号进栈*/
            break;                      /*若不是左括号,循环*/
        case ')':
        case ']':
        case '}':
            if(s.top==-1){             /*栈空*/
                cout<<"0";             /*属于第②种情况*/
                return ;
            }
            else{                       /*栈非空*/  
                GetTop(&s,&ch);         /*取栈顶元素*/  
                if(Match(ch,str[i]))    /*看当前右括号是否与栈顶做括号匹配*/
                    Pop(&s,&ch);        /*若匹配,栈顶左括号出栈*/
                else{
                    cout<<"0";          /*属于第①种情况*/
                    return ;
                }
            }
        }/*switch*/
    }/*for*/
    if(s.top==-1)
        cout<<"1";
    else 
        cout<<"0";                       /*属于第③种情况*/
}

int main(){
    SeqStack s;
    InitStack(&s);
    char ch;
    int i=0;
    char elem[MAXSIZE];
    while(1){
    
        cin>>ch;
        if(ch!='#'){
            elem[i]=ch;
            i++;
        }
        else break;
    }/*while*/
    BracketMatch(elem); /*PS:注意这里只需要把数组第一个地址(第一个元素首地址)传给形参*/
    return 0;
}    
后记:先要搞清楚每一种输出结果都代表着哪种情况或者是哪几种情况
先把思路弄清了,写起来更容易一点。
代码改错的过程也就是使自己对这道题逐渐清晰的过程。
  1. 判断一个数列是否是栈的输出序列

【问题描述】给出一个堆栈的输入序列,试判断一个序列是否能够由这个堆栈输出。如果能,返回总的出栈次数,如果不能,返回0。序列的输入及输出都是从左往右。(输入输出序列皆为整数且没有重复的数字,如果一个数字在输入序列中没有出现,那么其在输出序列中也不会出现)

【输入形式】第一行为输入序列的长度,然后为输入序列的数字;第二行为输出序列的数字。输入数据以空格隔开。

【输出形式】如果是一个出栈序列,则返回总的出栈次数, 否则返回0

【样例输入】

5 1 2 3 4 5

1 2 3 4 5

【样例输出】5

【样例说明】第一行输入的第一个数字是序列的长度,1 2 3 4 5 输入序列,以空格隔开,输出的总的出栈次数。

首先要搞明白”什么是栈的输出序列“。
理解:

#include<bits/stdc++.h>
using namespace std;
#define MAXSIZE 50
#define FALSE 0
#define TRUE 1
typedef int ElemType;
typedef struct{
    ElemType data[MAXSIZE];
    int top; 
 }SeqStack;

void InitStack(SeqStack *s){
    s->top=-1;
}

int Push(SeqStack *s,ElemType e){
    if(s->top==MAXSIZE-1)
        return FALSE;
    s->top++;                             /*s->top++写在元素赋值前面*/
    s->data[s->top]=e;
    return TRUE;
}

int Pop(SeqStack *s,ElemType *x){
    if(s->top==-1)
        return FALSE;
    *x=s->data[s->top];
    s->top--;
    return TRUE;
}

int main(){
    SeqStack s;
    InitStack(&s);
    int n;
    int k1=1;
    int k2=0;
    int flag=0;
    int item1[40];
    int item2[40];        
    int count=0;
    ElemType e;
    cin>>n;                                /*输入入栈元素个数*/
    for(int i=0;i<n;i++)
        cin>>item1[i];
    for(int i=0;i<n;i++)
        cin>>item2[i];
    for(k1=0;k1<n;k1++){
        Push(&s,item1[k1]);                /*输入序列元素一个一个入栈*/
        while(s.data[s.top]==item2[k2]&&k2<n){   /*如果当前输入序列栈顶元素和输出序列当前元素相等,则栈顶元素出栈*/
            Pop(&s,&e);
            count++;
            k2++;
        
        }/*while*/
    }/*for*/
    if(s.top==-1)
        flag=1;
    if(flag==1)
        cout<<count;
    else
        cout<<0;
    return 0;
}
  1. 字符串镜像

【问题描述】试写一个算法,识别依次读入的一个以“@”为结束符的字符序列是否为形如 “序列1&序列2” 模式的字符序列。其中序列1和序列2都不含字符 “&”,且序列2是序列1的逆序列。例如,“ a+b&b+a ”是属该模式的字符序列,而 “1+3&3-1”则不是。

【输入形式】

以@为结尾的一串字符

【输出形式】

若符合模式则输出字符串长度,否则输出no

【样例输入】

a+b&b+a@

【样例输出】

3

【注意】本题务必使用顺序栈或者链式栈的一种来实现,否则不给分。

#include<iostream>
#include<malloc.h>
using namespace std;
typedef int QElementType;
typedef struct Node* NodePtr;
typedef struct SNode* Stack; //栈 

struct Node{       //链队列结点的结构体 
    QElementType data;
    NodePtr next;
};
struct QNode{//链队列的头结点 
    struct Node* front;//队头指针,指向第一个元素 
    struct Node* rear;//队尾指针,指向最后一个元素的下一个位置 
};

struct SNode{
    QElementType data;
    struct SNode *next;
}; 

void InitQueue(QNode &Q){
    //构造一个空队列
    Q.front=Q.rear= (NodePtr)malloc(sizeof(struct Node));
    if(!Q.front) cout<<"分配空间失败!";
    Q.front->next=NULL; 
}

void EnQueue(QNode &Q,QElementType e){//Q是头结点指针 
    //插入元素e为Q的新的队尾元素
    NodePtr p=(NodePtr)malloc(sizeof(struct Node));
    if(!p) cout<<"分配空间失败!"; 
    p->data=e; 
    p->next=NULL;
    Q.rear->next=p;
    Q.rear=p;}

QElementType DeQueue(QNode &Q){//出队列 
    QElementType e;
    if(Q.front==Q.rear) return 0;
    NodePtr p=(NodePtr)malloc(sizeof(struct Node));
    p=Q.front->next;
    e=p->data; 
    Q.front->next=p->next;
    if(Q.rear==p) Q.rear=Q.front;
    free(p);
    return e;
}

//链栈 
void Push(QElementType e,Stack S){//入栈
    Stack p=(Stack)malloc(sizeof(struct SNode));
    p->data=e;
    p->next=S->next;
    S->next=p;
}
QElementType Pop(Stack S){//出栈
    if(S){
        QElementType e;
        Stack p=(Stack)malloc(sizeof(struct SNode));
        p=S->next ;
        e=p->data;
        S->next=p->next;
        free(p);
        return e;
    } 
    
} 
int main(){
    int n; 
    cin>>n;
    QElementType e,item1,item2;
    QNode Q;
    InitQueue(Q);
    Stack S;
    S=(Stack)malloc(sizeof(struct SNode));
    S->next=NULL;
    
    for(int i=0;i<n;i++){
        cin>>e;
        EnQueue(Q,e);
    }
    for(int i=0;i<n;i++){
        item1=DeQueue(Q);
        Push(item1,S);
    }
    for(int i=0;i<n;i++){
        item2=Pop(S);
        cout<<item2<<" ";
    }
}
  1. 等值字串

【问题描述】如果字符串的一个子串(其长度大于1)的各个字符均相同,则称之为等值子串。试设计一算法,求出串S中一个长度最大的等值子串;如果串S 中不存在等值子串,则输出信息no

【输入形式】输入一个字符串,并以!结束

【输出形式】输出第一个出现的最长字符串,如果没有输出no

【样例输入】aabc123abc123cc!

【样例输出】aa

【样例输入】abceebccadddddaaadd!

【样例输出】ddddd

#include<bits/stdc++.h>
using namespace std;
#define MAXSIZE 40
typedef char ElemType;
typedef struct{
    ElemType ch[MAXSIZE];
    int lengh;
}SeqStr;

void InitSeqStr(SeqStr *s){
    s->lengh=0;
}

void InPut(SeqStr *s){
    int i=-1;
    while(1){
        ElemType ch1;
        cin>>ch1;
        if(ch1!='!'){
            i++;
            s->ch[i]=ch1;
            s->lengh++;
        }
        else break;
    }
}

int Search(SeqStr *s){
    ElemType Maxlen=1;            /*每次比较所产生的最长连续字符的长度*/    
    ElemType tempCh;              /*临时最长字符*/
    int tempCount=1;              /*临时计数器*/
    for(int i=1;i<s->lengh;i++){  /*比较前面的字符与当前字符是否相等*/
        if(s->ch[i]==s->ch[i-1]){ 
            tempCount++;          /*若相等,当前字符个数加1*/
        }
        else tempCount=1;         /*若不相等,则将临时计数器初始化为1*/
        if(tempCount>Maxlen){     /*当前字符长度比上一种字符长*/
            tempCh=s->ch[i];      /**/  
            Maxlen=tempCount;
        }
    }
    if(Maxlen>1)
        for(int i=0;i<Maxlen;i++)
            cout<<tempCh;
    else
        cout<<"no";
    return 0;
}

int main(){
    SeqStr s;
    InitSeqStr(&s);
    InPut(&s);
    Search(&s);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值