zoukankan      html  css  js  c++  java
  • DS博客作业02--栈和队列

    这个作业属于哪个班级 数据结构--网络2011/2012
    这个作业的地址 DS博客作业02--栈和队列
    这个作业的目标 学习栈和队列的结构设计及运算操作
    姓名 王鑫

    0.PTA得分截图

    1.本周学习总结

    1.1栈

    • 顺序栈(存储的空间是顺序的)

    栈只能在一端进行插入和删除,设置顺序栈的的结构体时,用一个top来表示用来删除和插入的栈顶。顺序栈就像一个特殊的数组,只对top表示下标的栈元素改动。

    typedef struct {
    	elementType data[Max];//存放数据
    	int top;//用来插入删除
    	int MaxSize;//堆栈最大容量
    }SqStack;
    

    top=-1;//栈空条件
    top=MaxSize-1;//栈满条件
    top++;st->data[st->top]=e;//进栈操作
    e=st->data[st->top];top--;//退栈操作

    • 初始化栈
    void InitStack(SqStack& s)
    {
    	s = new Stack;
    	s->top = -1;
    }
    
    • 销毁栈
    void DestroyStack(SqStack& s)
    {
    	delete s;
    }
    
    • 进栈
    bool Push(SqStack& s, ElementType e)
    {
    	if (s->top == MaxSize - 1)//如果栈为满的时候
    		return false;//返回错误
    	s->top++;
    	s->data[s->top] = e;
    	return true;
    }
    
    • 出栈
    bool Pop(SqStack& s, ElementType& e)
    {
    	if (s->top == -1)//栈为空的时候,返回false
    		return false;
    	e = s->data[s->top];//取栈顶元素
    	s->top--;//栈顶指针-1
    	return true;
    }
    
    • 取栈顶元素
    bool GetTop(SqStack* s, ElementType& e)
    {
    	if (s->top == -1)//栈为空的时候,返回false
    		return false;
    	e = s->data[s->top];//取元素,并不移动指针
    	return true;
    }
    
    • 链栈(采用链式存储数据,空间分配不是顺序的)
      数据定义
    typedef struct linkknode
    {
    	ElementType data;//数据域
    	struct linknode* next;//指针域
    }LiNode, * LiStack;
    

    链栈的操作函数

    • 初始化栈
    void InitStack(SqStack& s)
    {
    	s = new Stack;
    	s->next = NULL;
    }
    
    • 销毁栈
    
    void DestroyStack(SqStack& s)
    {
    	LiStack node;
    	while (s != NULL)
    	{
    		node = s;
    		s = s->next;
    		delete node;
    	}
    }
    
    • 判断栈是否为空
    bool StackEmpty(LiStack s)
    {
    	return (s->next == NULL);
    }
    
    • 进栈//头插法来插入
    bool Push(SqStack& s, ElementType e)
    {
    	LiStack p;
    	p = new LiNode;//申请新的节点
    	p->data = e;//赋值给它
    	p->next = s->next;//插入p节点
    	s->next = p;
    }
    
    • 出栈
    bool Pop(SqStack& s, ElementType& e)
    {
    	LiStack p;
    	if (s->next == NULL)//栈为空的时候,返回false
    		return false;
    	p = s->next;
    	e = p->data;
    	s->next = p->next;//删除p节点
    	delete p;//释放p节点
    	return true;
    }
    
    • 取栈顶元素
    bool GetTop(SqStack* s, ElementType& e)
    {
    	if (s->next == NULL)//栈为空的时候,返回false
    		return false;
    	e = s->next->data;//取元素,并不移动指针
    	return true;
    }
    

    1.2栈的应用

    之前做小学生口算系统时,做有优先级的运算时,不好做处理。现在学习了栈,可以运用栈的先进后出的特点来实现优先级运算。

    中缀表达式 a+b*c+(d*e+f)*g
    转为后缀   abc*+de*f+g*+
    
    遍历中缀表达式
    if 算子直接->postexp[]
    else 运算符
    switch (运算符)
    {
    case'(':进数组postexp[]
    
    case')':Pop()出栈e
    	while (直到出栈的e为')')
    	{
    		e->postexp;
    		Pop(),出栈e
    	}
    case'+':
    case'-':
    	while (直到栈为空)
    	{
    		GetTop//取栈顶
    			if (栈顶e! = '(')
    			{
    				出栈;
    					进数组postexp;
    			}
    			else
    				break;
    	}
    
    	进栈我们现在遍历到的运算符
    
    case'*':
    case'/':
    	while (直到栈为空)
    	{
    		GetTop//取栈顶
    			if (栈顶为'+' || '-')
    				break;
    			if (栈顶e! = '*'||'/')
    			{
    				出栈;
    					进数组postexp;
    			}
    			else
    				break;
    	}
    	进栈我们现在遍历到的运算符
    
    
    default:
    	while (*exp旧数组为数字)
    	{
    		进新数组;
    			exp++;
    	}
      }
    
    while (栈不为空时)
    {
    	出栈;
    	进新数组postexp;
    }
    postexp[i] = 0;//结束标志
    
    
    后缀表达式求值
    遍历后缀表达式
    遇见数字入栈
    遇见操作符时一次出栈操作数 b,a 做运算 a op b ,结果入栈
    遍历完成后栈内的那个元素即是结果
    

    1.3队列


    队列和栈的不同就是队列两个端口都能用,不过一般队头出队,队尾进队。
    这样队列的特点就是先进先出。队列的结构体设计,有两个指针,一个用来表示队头一个用来表示队尾。

    typedef struct
    {
        ElemType data[MaxSize];
        int front, rear;//队头和队尾指针
    }Queue;
    

    front=rear;//队空的条件
    rear=MaxSize-1;//队满条件
    rear++;data[rear]=e;//e进队
    front++;e=data[front];//e出队

    • 初始化队列
    void InitQueue(SqQueue& q)
    {
        q = new Queue;
        q->front = q->rear = -1;
    }
    
    • 销毁队列
    void DestroyQueue(SqQueue& q)
    {
        delete q;
    }
    
    • 判断函数是否为空
    bool QueueEmpty(SqQueue q)
    {
        return (q->front == q->rear);
    }
    
    • 进队列
    bool enQueue(SqQueue& q, ElemType e)
    {
        if (q->rear + 1 == MaxSize)
            return false;
        q->rear = q->rear + 1;
        q->data[q->rear] = e;
        return true;
    }
    
    • 出队列
    
    bool deQueue(SqQueue& q, ElemType& e)
    {
        if (q->front == q->rear)//队空
            return false;
        q->front = q->front + 1;
        e = q->data[q->front];
        return true; 
    }
    

    使用队列的时候,可能因为front前出队留下的空位,导致rear=MaxSize-1作为队满条件不满足,出现假溢出。
    这时候我们逻辑上让这个队列前后连接起来,形成一个环状的顺序表,称为环形队列或循环队列。

    环形队列结构的结构体设计和不同的队列没有什么不同

    typedef struct
    {
        ElemType data[MaxSize];
        int front, rear;//队头和队尾指针
    }Queue;
    
    • 初始化环形队列
    void InitQueue(SqQueue& q)
    {
        q->new Queue;
        q->front = q->rear = 0;//设置在最初的一位数上
    }
    
    • 销毁环形队列
    void DestroyQueue(SqQueue& q)
    {
        delete q;
    }
    
    • 判断环形队列是否为空
    void QueueEmpty(SqQueue& q)
    {
        return (q->front==q->rear)
    }
    
    • 进环形队列
    bool enQueue(SqQueue& q, ElemType e)
    {
        if ((q->rear + 1) % MaxSize == q->front)//队满
            return false;
        q->rear = (q->rear + 1) % MaxSize;
        q->data[q->rear] = e;
        return true;
    }
    
    • 出环形队列
    bool deQueue(SqQueue& q, ElemType e)
    {
        if (q->rear == q->front)//队空
            return false;
        e = q->data[q->front];
        q->front = (q->front + 1) % MaxSize;
        return true;
    }
    

    链式队列存储

    队列用链式存储时,设立两个指针来指向队头和队尾。但这两个指针里面没有存放数据。

    • 链队列结构体设计
    typedef struct qnode {
        ElemType data;
        struct qnode* next;
    }QNode;
    
    //链队列中头指针为指针类型
    typedef struct
    {
        QNode* front;
        QNode* rear;
    }LinkQueue;
    
    • 初始化链队
    //这个是带头节点的链队
    Status InitQueue(LinkQueue& Q)
    {
        Q.front = Q.rear = new QNode;
        if (!Q.front)exit(OVERFLOW);
        Q.front->next == NULL;
        return OK;
    }
    
    • 判断是否为空
    Status QueueEmpty(LinkQueue& Q)
    {
        return (Q.front == Q.rear);
    }
    //取链队的队头元素
    Status GetHead(LinkQueue& Q,ElemType &e)
    {
        if (Q.front == Q.rear)return ERROR;
        e = Q.front->next->data;//除头结点的第一个节点的数据
        return OK;
    }
    
    • 入队和出队
    Status EnQueue(LinkQueue& Q, ElemType& e)
    {
        p = new QNode;
        if (!p)exit(OVERFLOW);
        p->data = e;
        p->next = NULL;
        Q.rear->next = p;
        Q.rear = p;
        return OK;
    }
    
    Status DeQueue(LinkQueue& Q, ElemType& e)
    {
        if (Q.front == Q.rear)return ERROR;
        p = Q.front->next;
        e = p->data;
        Q.front->next = p->next;
        if (Q.rear == p)
            Q.rear = Q.front;//最后一个元素被删,改队尾
        delete p;
        return OK;
    }
    

    2.PTA实验作业

    2.1符号配对

    2.1.1伪代码

    将数据传入字符型数组st
    
    for (直到st的结尾)
    {
    	if (st为"/*")
    	{
    		进s[];//用<代替/*
    	}
    	else if (st == '(' || '[' || '{')
    	{
    		进s[];//进栈
    	}
    	else if (st为 * / )
    	{
    		if (栈顶为 < )
    		{
    			Pop()//出栈
    		}
    		else
    		{
    			printf("NO
    ");
    			if (top - 1)//栈内无元素
    				printf("?-*/
    ");//缺失左符号
    			else
    				printf("%c-?
    ", c);//缺失右符号
    			结束函数//return 0
    		}
    	}
    	else if (st == ')' || ']' || '}')
    	{
    		if[s的栈顶是三个之中的一个配对符号]
    		{
    			出栈
    		}
    		else
    			if (top == -1栈内无元素)
    				printf("?-%c
    ", st[i]);
    			else
    				printf("%c-?
    ", c);//缺失右符号
    		< 要单独处理
    
    			结束函数
    	}
    }
    	if(top == -1)//在经过上面的处理后,栈内为空
    	{
    	输出:YES;
        }
    	else
    	{
    		输出:NO
    			输出:栈内第一个 - ? ;
         }
    

    2.1.1解题思路

    遍历数组
    if算子
    进新的数组
    else
    判断与前一位的优先级
    前一位高则出栈,进新数组直到比现在这位低的优先级,然后进栈本位
    前一位没有比本位高,进栈本位
    

    2.1.2 总结解题所用知识点

    • 1.char ch[1000];//用来和栈内符号匹配 比较灵活
      ch[')'] = '(';
      ch[']'] = '[';
      ch['}'] = '{';
      用空间来换时间,设立一个字符型数组,用它们的ASCII码做下标,之后我们
      就可以更灵活的来找匹配的符号。像:
      s[top] == ch[st[i]]
      我们要找')'的时候就能用ch[')']来表示我们要找的'('

    • 2.题目中有'/'和'/',这两个都是两个字符,我们判断出后可以使用'<'和'>'来代替入栈,这样后期符号匹配比较好找

    2.2银行业务队列简单模拟

    2.2.1伪代码

    for (i < max; i++)
    {
    	奇数进 odd栈
    		偶数进 even栈
    }
    while (i < max)
    	{
    	if (flag < 2)
    	{
    	if (odd不为空)
    	{
    	输出e
    	flag++;
    	}
    	}
    	else
    	{
    	even出栈
    	输出even出栈的元素
    	flag = 0;
    	}
    	if (i != max - 1)//还没到最后一位数
    				cout << " ";//数字后输出空格
    	if (odd为空,even不为空)
    	(
    	将odd剩下的按格式输出
    		}
    else if(even为空,odd不为空)
    	{
    		将even剩下的按格式输出
    	}
    
    

    2.2.1解题思路

    分两个队列odd和even,分别为奇数偶数
    每输出两个奇数,就输出一个偶数
    if其中一个为空的时候
    将剩下的输出
    

    3.阅读代码

    3.1题目及解题代码


    3.2该题的设计思路

    先按照身高排队
    
    再根据前面人数再排
    遍历(从高到矮)
    如果k=0,放到第一个,
    k有数字就判断已经进去的人,来判断本次放在哪
    

    3.3难点

    • 有两个判断顺序的标准,先用一个标准拍好序,再根据第二个标准做第二次调整

    3.3 O(n)

    因为遍历一遍后还要再判断本次位置,O(n^2)
    空间复杂度:O(n),即为排序需要使用的栈空间

  • 相关阅读:
    SQL SERVER 全文索引分词
    Json官方介绍
    SQL Try Catch(转载http://www.cnblogs.com/jimmyray/archive/2011/08/02/2125069.html)
    SQL函数记录
    SQL事务处理代码(SQL Server 2000 & 2005)
    SQL通用分页存储过程
    [导入]SoapExtension 1.0 的问题与解决
    BugTracker.NET 汉化手札
    [导入]我对J2EE和.NET的一点理解
    PostgreSQL 8.0.2 应用报告
  • 原文地址:https://www.cnblogs.com/xiechi/p/14617334.html
Copyright © 2011-2022 走看看