王道考研408 数据结构 第三章 栈、队列与数组

第三章 栈、队列与数组

3.1 栈

3.1.03

假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。(已存入一维数组中)

bool judge(char a[])
{
    int i = 0, cnt = 0;
    while(a[i]!='\0')
    {
        if(a[i]=='I') cnt++;
        else if(a[i]=='O') cnt--;
        if(cnt<0) return false;// too much in
    }
    if(cnt!=0) return false;
    return true;
}
3.1.04

单链表,表头指针L,结点结构data和next,判断n个字符是否中心对称。

//用头插法先把前半部分颠覆,然后慢慢存,空间复杂度应该是O(1),时间复杂度为O(n)
typedef struct LinkList{
    ElemType data;
    LNode *next;
}LNode,*LinkList;
bool symmetry(LinkList &L)
{
    LNode *p, *q, *r;
    LinkList M = (LinkList)malloc(sizeof(LNode));
    M->next == NULL;
    p = M;
   	q = L->next;
    r = q->next;
    for(int i = 0; i<n/2; i++){
		q->next  = M->next;
        M->next = q;
        q = r;
        r = r->next;
    }
    //now it's (an/2,...,a2,a1),and q points to the late half part of chain which includes mid
    if(n%2==1) L->next = r;
    else L->next = q;
    p = M->next;
    q = L->next;
    while(q!=NULL)
    {  
        if(p->data == q->data){
            p = p->next;
            q = q->next;
        }
        else return false;
    }
    return true;
}
//标准答案是存入栈的,因为这一章是栈而且还是得学,我再复现一下
int dc(LinkList L, int n)
{
    int i;
    LNode *p;
    char s[n/2];
    p = L->next;
    for(i = 0; i<n/2; i++){
        s[i] = p->data;
        p = p->next;
    }
    i--;//恢复最后的i值
    if(n%2 ==1)
        p = p->next;//奇数判断
    while(p!=NULL && s[i]==p->data){
		i--;
        p = p->next;
    }
    if(i==-1)//空栈
        return 1;
    else return 0;
}
3.1.05

设有两个栈S1,S2都采用顺序栈方式,并且共享一个存储区[O…maxsize-1],为了尽量利用空间,减少溢出的可能,可采用栈顶相向,迎面增长的存储方式。

// define inn
#define maxsize 100
#define  ElemType int
typedef struct{
	ElemType stack[maxsize];
 	int num[2];//record the point of inn   
}stack;
stack k;
k.num[0] = -1;
k.num[1] = maxszie;
int push(ElemType data, int inn_num)
{
    if(inn_num>1||inn_num<0) return -1; //over bundary
    if(num[0]-num[1]<=1){
    	printf("full!"); //毫无意义    
        return -1;
    }
 	switch(i){
        case 0: k.stack[++num[0]]=data; return 1; break;
        case 1: k.stack[--num[1]]=data; return 1; break;
    }   
    return 0;
}
ElemType pop(int i)
{
    if(i<0||i>1) exit(-1);
    switch(i){
        case 0: 
            if(num[0] == -1){
                printf("empty!");
                return -1;
            }
            else return k.stack[num[0]--];
            break;
        case 1:
            if(num[1] == maxsize){
                printf("empty!");
                return -1;
            }
            else return k.stack[num[1]++];
    }
   return 0;
}
后记

return与exit之我见

看到答案里有用exit的return -1的情况,感觉很迷惑,return -1理论上指的也是错误返回,exit(0)是正常退出,但是他越界等错误,应该exit(-1)差不多,后来查了查,如果出现这种错误,说明程序彻底错了,这个时候就应该exit(0)(我感觉用什么数字都可以)正常结束一整个程序而不是这个function。如果是栈空等基本操作的时候就会返回return -1,但是返回0是正常还是1是正常也是很多元化,我的评价是没啥区别,凑合凑合都能用。

3.2 队列

3.2.01

若希望循环队列中的元素都能得到利用,则需设置一个标志域tag,并以tag的值为0或1来区分队头指针front和队尾指针rear相同时的队列状态是“空”还是“满”。试编写与此结构相应的入队和出队算法。

#define MaxSize 50
typedef struct{
    int tag;
    int front, rear;
    int data[MaxSIze];
}Queue;
int EnQueue(Queue &L, ElemType x)
{
    if(Q.front == Q.rear && Q.tag == 1) exit(-1);
    Q.rear = (Q.rear+1)%MaxSize;
    Q.tag = 0;
    return 1;
}
int DeQueue(Queeu &L, ElemType &x)
{
    if(Q.rear==Q.front && Q.tag == 0) exit(-1);
    x = Q.data[Q.front];
    Q.front = (Q.front+1)%MaxSize;
    Q.tag = 0;
    return 1;
}
3.2.03

利用两个栈S1,S2来模拟一个队列,已知栈的4个运算定义如下:
Push(S,x);//元素x入栈
Pop(S,x) ;//S出栈并将出栈的值赋给x
StackEmpty(S) ;//判断栈是否为空
StackOverflow(S) ;// 判断栈是否满
如何利用栈的运算来实现该队列的3个运算(形参根据要求自己设计)?
Enqueue ;//将元素x入队
Dequeue ;//出队,并将出队元素存储在x中
QueueEmpty;/ /判断队列是否为空

思路:woc这也太难了,利用两个栈S1和S2来模拟一个队列,当需要向队列中插入一个元素时,用S1来存放已经输入的元素,需要出队的时候用S2执行操作。感觉有点像倒筒子,这题真的出的稀烂!

void Enqueue(Stack &S1, Stack &S2, ElemType x)
{
    if(!StackOveflow(S1)){
       Push(S1,x);
        return 1;
    }
    if(StackOverFlow(S1)&&!StackEmpty(S2)){
        exit(-1);//队列满
    }
    while(!StackEmpty(S1)){
        Pop(S1,x);
        Push(S2,x);
    }
    Push(S1,x);
    return 1;
}

void DeQueue(Stack &S1, Stack &S2, ElemType &x)
{
    if(!StackEmpty(S2)) Pop(S2,x);
    else if(StackEmpty(S1)){
        printf("队列为空");
        return -1;
    }
    else{
        while(!StackEmpty(S1)){
            Pop(S1,x);
            Push(S2,x);
        }
        Pop(S2,x);
    }
}

int QueueEmpty(Stack &S1, Stack&S2)
{
    if(StackEmpty(S1)&&StackEmtpy(S2)) return 1;
    return 0;
}

3.3 栈和队列的应用

3.3.01

假设一个算数表达式中包含圆括号、方括号和花括号3种类型的括号,编写一个算法来判别表达式中的括号是否配对,以字符’\0’作为结束符

bool match(char a[])
{
    InitStack(S);
    int i = 0;
    while(str[i]!='\0'){
        switch(str[i]){
            case '(': Push(S,'('); break;
            case '[': Push(S,'['); break;
            case '{': Push(S,'{'); break;
            case ')': Pop(S,e); if(e!='(') return false; break;
            case ']': Pop(S,e); if(e!='[') return false; break;
            case '}': Pop(S,e); if(e!='{') return false; break;
            default: break;
        }
        i++;
    }
    if(!IsEmpty(S)){
        printf("不匹配捏");
        return false;
    }
    else{
        printf("匹配");
        return true;
    }
}
3.3.02

按下图所示铁道进行车厢调度(注意,两侧铁道均为单向行驶道,火车调度站有一个用于调度的“栈道”), 火车调度站的入口处有n节硬座和软座车厢(分别用H和S表示)等待调度,试编写算法,输出对这n节车厢进行调度的操作(即入栈或出栈操作)序列,以使所有的软座车厢都被调整到硬座车厢之前。

img

void sort(char a[])
{
    char *q = a, tmp;
    InitStack(S);
    int i = 0;
    while(a[i]!='H'&&a[i]!='S'){
		if(a[i]=='H') push(S,a[i]);
        else *(q++)= a[i];
        i++;
    }
    while(!StackEmpty(s)){
        Pop(S,tmp);
        *(q++)  = tmp;
    }
}
3.3.04

某汽车轮渡口,过江渡船每次能载 10 辆车过江。过江车辆分别为客车类和货车类,上船有如下规定:同类车先到先上船,客车先于货车上渡船,且每上 4 辆客车,才允许上一辆货车;若等待客车不足 4 辆则以货车代替;若无货车等待则允许客车都上船。设计一个算法模拟渡口管理。

Queue q;//ferry
Queue q1;//passenger
Queue q2;//trunk
void manage_port() //p代表车列
{
    int i=0, j=0;
    while(j<10){
        if(!QueueEmpty(q1)&&i<4){
            DeQueue(q1, x);
            EnQueue(q, x);
        	i++;
            j++;
        }
        else if(!QueueEmpty(q2)&&i==4){
            DeQueue(q2, x);
            EnQueue(q, x);
            j++;
            i = 0;
        }
        else{ //passenger line is not full
            while(j<10&&i<4&&!QueueEmpty(q2)){
                DeQueue(q2, x);
                EnQueue(q, x);
                i++;
                j++;
            }
            i = 0;
        }
        if(QueueEmpty(q1)&&QueueEmpty(q2)) j = 11;
    }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值