2024 王道数据结构 代码习题部分 第三章 栈、队列、数组

第三章 栈、队列、数组

(一)

03.若I表示进栈操作,O表示出栈操作,栈的初态和终态为空。假设被判定的操作序列已存入一维数组中,判断所给序列是否合法。合法返回true,非法返回false。

bool Judge(char A[]){

    int push=0,pop=0;

    for(int i=0;A[i]!='\0';i++){

        switch(A[i]){

            case 'I' : push++;

            case 'O' : pop++;

        }

        if(pop>push)

            return false;

    }

    return push==pop;

}

04.设单链表的表头指针为L,结点结构为data next,data为字符型,判断该链表的全部n个字符是否中心对称。

bool JudgeSymmetry(LinkList L,int n){

    int top=-1;

    char S[n/2];

    LNode *r = L->next;

    for(int i=0;i<n/2;i++){     // 一半元素入栈

        S[++top] = r->data;

        r = r->next;

    }

    if(n%2==1)  // 奇数个字符-->跳过中间的字符

        r = r->next;

    while(r!=NULL){     // 遍历后半部分并对比

        if(r->data != S[top--])

            return false;

        r = r->next;

    }

    return true;

}

05.设有两个栈s1,s2都采用顺序栈方式,并共享一个存储区[0, ... ,maxsize-1]采用栈顶相向,迎面增长的方式。设计s1,s2有关入栈、出栈的操作算法。

typedef struct{

    ElemType data[MaxSize];

    int top1,top2;

}DSeqStack;

void InitStack(DSeqStack &S){

    S.top1 = -1;

    S.top2 = MaxSize;

}

bool Push(DSeqStack &S,int num,ElemType x){

    if(S.top1+1 = S.top2)

        return false;

    if(num==1)

        S.data[++S.top1] = x;

    if(num==2)

        S.data[--S.top2] = x;

    return true;

}

bool Pop(DSeqStack &S,int num,ElemType &x){

    if(num==1){

        if(S.top1==-1)

            return false;

        x = S.data[S.top1--];

        return true;

    }

    if(num==2){

        if(S.top2==MaxSize)

            return false;

        x = S.data[S.top2++];

        return true;

    }

}

(二)队列

01.希望循环队列中的元素都能得到利用,设置tag域,以tag的0/1区分头尾指针相同时,队列状态是空还是满,编写相应的入队出队算法。

typedef struct{

    ElemType data[MaxSize];

    int front,rear;

    bool tag;

}SeqQueue;

bool InitQueue(SeqQueue &Q){

    Q.rear = Q.front = 0;

}

bool EnQueue(SeqQueue &Q,ElemType x){

    if(Q.rear==Q.front && Q.tag==1)

        return false;

    Q.data[Q.rear] = x;

    Q.rear = (Q.rear+1)%MaxSize;

    Q.tag = 1;

    return true;

}

bool DeQueue(SeqQueue &Q,ElemType &x){

    if(Q.rear==Q.front && Q.tag==0)

        return false;

    x = Q.data[Q.front];

    Q.front = (Q.front+1)%MaxSize;

    Q.tag = 0;

    return true;

}

02.Q是一个队列,S是一个空栈,实现将队列中的元素逆置的算法。

typedef struct{

    ElemType data[MaxSize];

    int top;

}SeqStack;

typedef struct{

    ElemType data[MaxSize];

    int front,rear;

}SeqQueue;

void InitStack(SeqStack &S){

    S.top = -1;

}

void InitQueue(SeqQueue &Q){

    Q.rear = Q.front = 0;

}

bool Push(SeqStack &S, ElemType x){

    if(S.top==MaxSize-1)

        return false;

    S.data[++S.top] = x;

    return true;

}

bool Pop(SeqStack &S,ElemType &x){

    if(S.top==-1)

        return false;

    x = S.data[S.top--];

    return true;

}

bool EnQueue(SeqQueue &Q, ElemType x){

    if((Q.rear+1)%MaxSize==Q.front)     // 队满

        return false;

    Q.data[Q.rear] = x;

    Q.rear = (Q.rear+1)%MaxSize;

    return true;

}

bool DeQueue(SeqQueue &Q, ElemType &x){

    if(Q.rear==Q.front)

        return false;

    x = Q.data[Q.front];

    Q.front = (Q.front+1)%MaxSize;

    return true;

}

bool Reverse(SeqQueue &Q,SeqStack &S){

    ElemType x;

    while(DeQueue(Q,x))  // 正常是先判空再进行操作,此处较为巧妙,合二为一。

        Push(S,x);

    while(Pop(S,x))

        EnQueue(S,x);

}

03.利用两个栈S1,S2模拟一个队列,已知栈的四个运算定义如下。Push(S,x);Pop(S,x);StackEmpty(S) ;StackOverflow(S);  如何利用栈的运算实现该队列的3个运算。Enqueue;Dequeue;QueueEmpty;

bool QueueEmpty(SeqStack S1,SeqStack S2){

    return StackEmpty(S1) && StackEmpty(S2);

}

// 思路:S1的入栈作为入队(若S1满,保证S2为空才能全部转移到S2中)     S2的出栈作为出队(出队时要把S1的元素入栈S2,S2再出栈)

bool EnQueue(SeqStack &S1,SeqStack &S2,ElemType x){

    ElemType temp;

    if(!StackOverFlow(S1)){     // S1未满

        Push(S1,x);

        return true;

    }else if(StackOverFlow(S1) && StackEmpty(S2)){  // S1满 S2空

        while(!StackEmpty(S1)){

            Pop(S1,temp);

            Push(S2,temp);

        }

        Push(S1,x);

        return true;

    }else{      // S1满 S2非空

        return false;

    }

}

bool DeQueue(SeqStack &S1,SeqStack &S2){

    ElemType temp;

    if(!StackEmpty(S1) && StackEmpty(S2)){   // S1非空 S2空

        while(!StackEmpty(S1)){

            Pop(S1,temp);

            Push(S2,temp);

        }

        Pop(S2,temp);

        return true;

    }else if(!StackEmpty(S2)){

        Pop(S2,temp);

        return true;

    }else{

        return false;

    }

}

04.设计一个队列,初始时为空,入队时允许增加空间,出队后原有空间可以重复使用,整个队列占用空间只增不减,入队出队操作的时间复杂度为O(1).

typedef struct LNode{

    int data;

    struct LNode *next;

}LNode;

typedef struct{

    LNode *front,*rear;

}LiQueue;

void InitQueue(LiQueue &Q){

    Q.rear = Q.front = (LNode *)malloc(sizeof(LNode));  // 预留了一个结点

    Q.rear->next = Q.front;

}

void EnQueue(LiQueue &Q,ElemType x){

    if(Q.rear->next == Q.front){    // 入队后无空余结点

        Q.rear->data = x;

        // 创建一个空结点,以供下次入队使用

        LNode *q = (LNode *)malloc(sizeof(LNode));

        Q.rear->next = q;

        Q.rear = q;

        q->next = Q.front;

    }else{     // 有至少两个空余结点

        Q.rear->data = x;

        Q.rear = Q.rear->next;

    }

}

bool DeQueue(LiQueue &Q,ElemType &x){

    if(Q.rear==Q.front)

        return false;

    x = Q.front->data;

    Q.front = Q.front->next;

    return true;

}

(三)栈和队列的应用

01.一个算数表达式中包括()[]{}三种括号,编写算法判断表达式中括号是否配对,以字符'\0'作为算数表达式的结束值。

void BracketCheck(char *str){

    Stack(S);    InitStack(S);

    char temp;

    int index=0;

    while(str[index]!='\0'){

        if(str[index]=='(' || str[index]=='[' || str[index]=='{')

            Push(S,str[index]);

        if(str[index]==')' || str[index]==']' || str[index]=='}'){

            Pop(S,temp);

            if(str[index]==')' && temp!='(')    return false;   // 左、右括号单身

            if(str[index]==']' && temp!='[')    return false;

            if(str[index]=='}' && temp!='{')    return false;

        }

        i++;

    }

    return StackEmpty(S);    // 括号数量是否匹配

}

02.车厢调度,在单行道中间有一个调度站,共有n节车厢,硬座记为H,软座记为S。编写算法,输出对n节车厢进行调度的操作(入栈出栈)序列,使得所有软座调整在硬座之前。

void TrainOperate(char *train){

    Stack(S);   InitStack(S);

    char *out = train;

    char *r = train;

    char temp;

    while(*r){

        if(*r == 'H')

            Push(S,*r);     // 硬座 --> 进栈

        else

            *(out++) = *r;  // 软座 --> 调整到前部

        r++;

    }

    while(!StackEmpty(S)){

        Pop(S,temp);

        *(out++) = temp;

    }

}

// 知识点:'\0'---false     "\0"---true

// 当指针p指向一个字符串时,最初一次的 *p 和 *(p++) 是相同的,都是指向第一个字符

03.使用一个栈实现以下递归函数的非递归计算。

 Pn(x)=1  n=0       Pn(x)=2 * x     n=1    

 Pn(x)=2 * x * P_n-1(x)-2(n-1)P_n-2(x)  n>1

double Compute(int n,double x){

    typedef struct{

        int n;

        double out;

    }Deal;

    Stack(S);   InitStack(S);

    double out_0 = 1;

    double out_1 = 2*x;

    for(int i=n;i>=2;i--)

        S.data[++S.top].n = i;

    while(S.top>=0){

        S.data[top].out = 2 * x * out_1 - 2 * ((S.data[S.top].n)-1) * out_0;

        out_0 = out_1;

        out_1 = S.data[top].out;

        S.top--;

    }

    // n  (0    1)     2  3  4  5   栈顶 <----  栈底

    //   out0  out1   top

    // n  (0    1)     2      3  4  5   栈顶 <----  栈底

    //         out0   out1   top

    if(n==0)

        return 1;

    else if(n==1)

        return 2*x;

    else

        return out_1;

}

// 注意点:1)栈最后是空的,不能返回栈中的数据

04.某汽车轮渡口,船能载10辆车。车辆分为客车和货车,同类车先到先上船;客车先于货车上船,每上四辆客车才上一辆货车;若等待客车不足四辆则以货车代替;若无货车等待,允许客车都上船。

void Harbour(Queue &Ship,Queue &Car,Queue &Truck){

    int sum = 0;

    int num_car = 0;

    while(sum<10){

        if(!QueueEmpty(Car) && num_car<4){  // 客车先于货车上船

            DeQueue(Car,x);

            EnQueue(Ship,x);

            num_car++;

            sum++;

        }else if(num_car == 4 && !QueueEmpty(Truck)){   // 每上四辆客车才上一辆货车

            DeQueue(Truck,x);

            EnQueue(Ship,x);

            num_car = 0;

            sum++;

        }else if(num_car == 4 && QueueEmpty(Truck)){   // 若无货车等待,允许客车都上船

            while(sum<10 && QueueEmpty(Truck)){

                DeQueue(Car,x);

                EnQueue(Ship,x);

                sum++;

            }

        }else{

            while(sum<10 && num_car<4 && !QueueEmpty(Truck)){   // 等待客车不足四辆则以货车代替

                DeQueue(Truck,x);

                EnQueue(Ship,x);

                num_car++;

                sum++;

            }

        }

        if(QueueEmpty(Car) && QueueEmpty(Truck))

            sum = 999;

    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值