DS博客作业02--栈和队列

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

0.PTA得分截图

1.本周学习总结(0-5分)

1.1 栈

栈的代码定义

typedef struct {
	ElemType data[MaxSize];//存放元素
	int top=-1;//栈顶指针,下标
}SqStack;//顺序栈的类型

进栈

bool Push(SqStack &s,ElemType e)
{
    if(s->top == MAXSIZE - 1)    //判断是否栈满
    {
        return false;
    }
    s->data[s->top++] = e;    //入栈
    return true;
}

出栈

bool Pop(SqStack &s,ElemType e)
{
    if(StackEmpty(s))    //判断是否为空栈
    {
        return false;
    }
    e = s->data[s->top--];    //退栈
    return true;
}

取栈顶元素

bool GetTop(SqStack *s,ElemType &e)
{	
   if (s->top==-1)	//判断栈空 
    return false;
    e=s->data[s->top];//栈顶元素赋值为e
    return true;
}

判断栈空

bool StackEmpty(SqStack s)
{
    if(s->top == -1) //栈为空返回true
    {
        return true;
    }
    return false;
}

判断栈满

int FullStack(SqStack s)
{
	if (s->top == MaxSize-1)
		return true;
	else
		return false;
}

销毁栈

void DestroyStack(SqStack s)
{
   delete s;
}

链栈的结构、操作函数

定义

typedef struct StackNode
{
    ElemType data;
    struct StackNode *next;
}Node,*Stack;

初始化

bool InitStack(Stack &s)
{
    s = NULL;
    return true;
}

进栈

void Push(Stack& s, ElemType e)
{
	Stack p;
	p = new Node;
	p->data = e;		//新建节点p
	p->next = s->next;	//插入*p节点作为开始节点
	s->next = p;
}

出栈

bool Pop(Stack& s, ElemType& e)
{
	Stack p;
	if (StackEmpty(s))		//栈空的情况
		return false;
	p = s->next;			//p指向开始节点,从栈顶开始出栈
	e = p->data;
	s->next = p->next;		//删除*p节点
	delete p;				//释放*p节点
	return true;
}

取栈顶元素

bool GetTop(SqStack &s,ElemType e)
{
    if(StackEmpty(s))    //判断是否为空栈
    {
        return false;
    }
    e = s->data;    //取栈顶
    return true;
}

判断栈空

bool StackEmpty(Stack *s)
{
    if(s == NULL)
    {
        return true;
    }
    return false;
}

销毁栈

void DestroyStack(Stack &s)
{ 
   Stack p;
   while (s!=NULL)
   {   p=s; 	
       s=s->next;
       delete p; 
   }
 }

1.2 栈的应用

表达式
中缀表达式:运算符在操作数中间
后缀表达式:运算符在操作数之后
中缀表达式转为后缀表达式:
建立一个栈用于存放运算符,每个运算符号进栈时都要比较一下其和栈顶的的符号优先级大小
优先级比栈顶运算符高的入栈
优先级小于等于栈顶运算符时,将栈顶运算符弹出并输出

1.3 队列

画一个队列的图形,介绍如下内容。

定义

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

基本操作:

初始化

void InitQueue(SqQueue &q)
{	q=new Queue;
	q->front=q->rear=-1;
}

判断栈空

bool QueueEmpty(SqQueue q)
{
   return(q->front==q->rear);
}

判断栈满

bool QueueFULL(SqQueue q)
{
   return(q->rear==MaxSize-1);
}

进队

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;
}

销毁队列

void DestroyQueue(SqQueue &q)
{
  delete q;
}

环形队列的结构、操作函数

结构

typedef struct
{ElemType data[MaxSize] ;//存放队中元素
int front, rear;//队头和队尾指针
}SqQueue;

初始化

void InitQueue( SqQueue * &.q)
{ q= (SqQueue * )malloc( sizeof(SqQueue));
q-> front=q-> rear=0;
}

入队列

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-> front==q-> rear)//队空下溢出
            return false;
q->front=(q->front+1)%MaxSize;
e=q -> data[q -> front];
return true;
}

队空

void QueueEmpty(SqQueue * &q)
{

return(q-> front==q-> rear);
}

销毁

void DestroyQueue(SqQueue * &q)
{
     free(q);
}

链队列的结构、操作函数

结构

typedef struct qnode
{ElemType data;//存放元素
struct qnode * next;//下一个结点指针
} DatalNode;//链队数据结点的类

初始化

void InitQueue( LinkQuNde * &.q)
{ q= (LinkQuNde * )malloc( sizeof(LinkQuNde));
q-> front=q-> rear=NULL;
}

入队列

void enQueue(LinkQuNode * &q, ElemType e)
{
DataNode*p;
p= (DataNode * )malloc( sizeof( DataNode)); //创建 新结点
p-> data=e;
p-> next= NULL;
if (q-> rear== NULL)//若链队为空,则新结点既是队首结点又是队尾钻去
    q->front=q-> rear= P;
else//若链队不空
{ q-> rear-> next= P;//将结点p链到队尾,并将rear 指向它
q-> rear=p;
}
}

出队列

bool deQueue(LinkQuNode . &q. ElemType &e)
{
DataNode *t:
if(q-> rear== NULL)//原来队列为空
   return false;
t=q -> front;//t指向首结点
if (q-> front==q- > rear)
     q-> front=q-> rear= NULL;
else
   q> front=q-> front-> next;
e=t-> data;
free(t);
return true;

队空

bool QueueEmpty(LinkQueue * &q)
{

return(q-> rear==NULL);
}

销毁队

void DestroyQueue(LinkQuNode*&q)
{DataNode * pre=q > front, * p;//pre指向队首结点
if (pre!=NULL)
{
p=pre- > next;//p指向结点pre的后继结点
while (p!= NULL)//p不空循环
{free(pre) ;//释放pre结点
pre=p;P=P- > next;//pre、p同步后移
}
free(pre);//释放最后一个数据结点
}
free(q);//释放链队结点

队列应用

6-4 另类循环队列

只设队列头指针Front,不设尾指针Rear,而是另设Count记录队列中元素个数。编写算法实现队列的入队和出队操作。

ElementType DeleteQ(Queue Q)
{
    if (Q->Count == 0)
    {
        printf("Queue Empty\n");
        return ERROR;
    }
    Q->Count--;
    
    ElementType X;
    X= Q->Data[Q->Front];
    Q->Front = (Q->Front + 1) % Q->MaxSize;
    return X;
}
bool AddQ(Queue Q, ElementType X)
{
    if (Q->Count == Q->MaxSize)
    {
        printf("Queue Full\n");
        return false;
    }
    
    Q->Data[(Q->Front + Q->Count) % Q->MaxSize] = X;
    Q->Count++;
    return true;
}

2.PTA实验作业(4分)

此处请放置下面2题代码所在码云地址(markdown插入代码所在的链接)。如何上传VS代码到码云

2.1 符号配对

#include <iostream>
#include <stack>
#include <string>
using namespace std;
int main()
{
	stack <char>str;
	int i = 0, k = 0, count = 0;
	char sum[100];
	char select[100];
	while (sum[k] = getchar())
	{
		if (sum[k] == '(' || sum[k] == '{' || sum[k] == '[' || sum[k] == ')' || sum[k] == ']' || sum[k] == '}')
		{
			select[i++] = sum[k];
			count++;
		}
		else
		{
			if (sum[k] == '/')
			{
				sum[++k] = getchar();
				if (sum[k] == '*')
				{
					select[i++] = '<';
					count++;
				}
			}
			else if (sum[k] == '*')
			{
				sum[++k] = getchar();
				if (sum[k] == '/')
				{
					select[i++] = '>';
					count++;
				}
			}
		}
		if (sum[k] == '.')
		{
			sum[++k] = getchar();
			if (sum[k] == '\n')
				break;
		}
		k++;
	}
	for (i = 0; i < count; i++)
	{
		if (select[i] == '(' || select[i] == '[' || select[i] == '{' || select[i] == '<')
		{
			str.push(select[i]);
		}
		else
		{
			if (select[i] == ')' || select[i] == ']' || select[i] == '}' || select[i] == '>')
			{
				if (str.empty())break;
				if ((select[i] == ')' && str.top() == '(') || (select[i] == ']' && str.top() == '[') || (select[i] == '}' && str.top() == '{') || (select[i] == '>' && str.top() == '<'))
					str.pop();
				else
					break;
			}
		}
	}
	if (str.empty() && i == count)
		cout << "YES";
	else
	{
		cout << "NO" << endl;
		if (str.empty())
		{
			if (select[i] == '<')
				cout << "/*-?";
			else if (select[i] == '>')
				cout << "?-*/";
			else if (select[i] == '(' || select[i] == '[' || select[i] == '{')
				cout << select[i] << "-?";
			else
				cout << "?-" << select[i];
		}
		else
		{
			if (str.top() == '<')
				cout << "/*-?";
			else if (str.top() == '>')
				cout << "?-*/";
			else if (str.top() == '(' || str.top() == '[' || str.top() == '{')
				cout << str.top() << "-?";
			else
				cout << "?-" << str.top();
		}
	}
	return 0;
}

2.1.1 解题思路及伪代码

思路:
把各种题目要求的符号都存入一个数组中,其中/* ,*/符号的处理是,判断后以‘<’,‘>’的形式存入数组
再利用for循环遍历数组依次入栈,若能配对则出栈,不能则break
最后再判断要输出的内容

stack <char>str
	int i = 0, k = 0, count = 0
	char sum[100]
	char select[100]
	while (sum[k] = getchar())
	
		if sum[k] == '(' '{'  '['  ')'  ']' '}'
			select[i++] = sum[k]
			count++
		end if
		else
			if sum[k] == '/'
				sum[++k] = getchar()
				if sum[k] == '*'
					select[i++] = '<'
					count++
				end if
			end if
			else if sum[k] == '*'
				sum[++k] = getchar()
				if (sum[k] == '/')
					select[i++] = '>'
					count++
				end if
			end if
		if sum[k] == '.'
			sum[++k] = getchar()
			if sum[k] == '\n'
				break;
		end if
		k++
	end while
	for i=0 to count
		if select[i] 都是左符号
			入栈
		end if
		else
			if 都是右符号
				if 栈空 break
				if 各符号配对
					出栈
				else
					break
			end if
		
	end for
if栈空且i=len
  输出yes
else if栈空
  输出no
else
  输出栈顶和no
	return 0;

2.1.2 总结解题所用的知识点

读取字符,读取/**/
出栈,入栈 :左符号入栈,右符号配对时出栈,判断出栈或入栈或break

2.2 银行业务队列简单模拟

#include "stdio.h"
#include "iostream"
using namespace std;
#define MaxSize 1000  
typedef struct
{
    int data[MaxSize];
    int front, rear;
} SqQueue;
void InitQueue(SqQueue*& q);
int main()
{
    int num[MaxSize];
    int n;
    int i;
    int e;
    int count=0;
    SqQueue* A, * B;
    cin >> n;
    for (i = 0; i < n; i++)
    {
        cin >> num[i];
    }
    InitQueue(A);
    InitQueue(B);
    for (i = 0; i < n; i++)
    {
        if (num[i] % 2 == 1)
        {
            A->rear = (A->rear + 1) % MaxSize;
            A->data[A->rear] = num[i];
        }
        else
        {
            B->rear = (B->rear + 1) % MaxSize;
            B->data[B->rear] = num[i];
        }
    }
    while (A->front != A->rear || B->front != B->rear)
    {
        for (i = 1; i <= 2; i++)
        {
            if (A->front != A->rear)
            {
                A->front = (A->front + 1) % MaxSize;
                e = A->data[A->front];
                count++;
                if (count < n)
                {
                    cout << e<<' ';
                }
                else
                {
                    cout << e;
                }
            }
        }
        if (B->front != B->rear)
        {
            B->front = (B->front + 1) % MaxSize;
            e = B->data[B->front];
            count++;
            if (count < n)
            {
                cout << e << ' ';
            }
            else
            {
                cout << e;
            }
        }
    }
    return 0;
}
void InitQueue(SqQueue*& q)
{
    q = (SqQueue*)malloc(sizeof(SqQueue));
    q->front = q->rear = 0;
}

2.2.1 解题思路及伪代码

思路:
先把编号都存入一个数组中,再利用for循环,把奇数的编号压入A栈,偶数的编号压入B栈,再利用while循环,先进行2次A栈的出队,再进行一次B栈的出队,直到A、B栈都空

int num[MaxSize]
    int n
    int i
    int e
    int count=0
    SqQueue* A, * B
    cin >> n
    for i=0 to n
        cin >> num[i]
    end for
    InitQueue(A)
    InitQueue(B)
    for i=0 to n
        if (num[i] % 2 == 1)
        then
            A->rear = (A->rear + 1) % MaxSize
            A->data[A->rear] = num[i]
        end if
        else
            B->rear = (B->rear + 1) % MaxSize
            B->data[B->rear] = num[i]
    end for
    while (A->front != A->rear || B->front != B->rear)
        for i=1 to 2
            if (A->front != A->rear)
            then
                A->front = (A->front + 1) % MaxSize
                e = A->data[A->front]
                count++
                if (count < n)
                then
                    cout << e<<' '
                end if
                else
                    cout << e
            end if
        end for
        if B->front != B->rear
            B->front = (B->front + 1) % MaxSize
            e = B->data[B->front]
            count++
            if count < n
            then
                cout << e << ' '
            else
                cout << e
            end if
        end if
    end while
    return 0

2.2.2 总结解题所用的知识点

队列的出队和入队
输出顺序的判断

3.阅读代码(0--1分)

3.1 题目及解题代码

考研题

题目:一个正读和反读都相同的字符序列称为“回文”。例如“abcba”和“1221”是回文,而“abcde”不是回文。试写一个算法,要求利用栈的基本运算识别一个以@为结束符的字符序列是否是回文。

Status HuiWen(String str)
{ 
InitStack(&s1);//构造两个空栈  
InitStack(&s2);  
i=0;  
while(str[i++]!='@')   
Push(&s1,ch);//将字符压入栈s1  
length=StackLength(s1);//length表示字符个数   
for(i=0;i<length/2;i++)   
Push(&s2,Pop(&s1,&e);//将s1中一半的字符逐个压入s2中    
if(length%2!=0)  //如果栈中元素为奇数个,需要去除s1的栈顶元素,也就是字符序列中间的一个字符   
Pop(&s1,&e);   
for(i=0;i<length/2;i++)   
if(Pop(&s1,&e1)!=Pop(&s2,&e2))//e1和e2不等    
return false;  //有一个不相等就不是回文,直接结束程序  
printf(yes);//运行到此步说明两栈字符相等   
DestroyStack(s1);  //销毁  
DestroyStack(s2); 
}//end 

3.2 该题的设计思路及伪代码。

思路:将字符序列顺序压入栈1中,然后将栈1中的一半的字符(这里取商的下界,也就是说如果长度为5,一半表示2,长度为7,一半表示3)逐个压入栈2中,如果两个栈相等,那么是回文,否则不是

InitStack(&s1)构造两个空栈  
InitStack(&s2)  
i=0
while str[i++]!='@'  
  Push(&s1,ch) 将字符压入栈s1  
end while
length=StackLength(s1)length表示字符个数   
for i=0 to length/2
  Push(&s2,Pop(&s1,&e)  将s1中一半的字符逐个压入s2中    
end for
if length%2!=0 如果栈中元素为奇数个,需要去除s1的栈顶元素,也就是字符序列中间的一个字符   
  Pop(&s1,&e) 
end if
for i=0 to length/2
  if Pop(&s1,&e1)!=Pop(&s2,&e2) e1和e2不等    
    return false 有一个不相等就不是回文,直接结束程序  
  end if
end for
printf(yes)运行到此步说明两栈字符相等   
DestroyStack(s1)  //销毁  
DestroyStack(s2) 
}//end 

时间复杂度:O(n)
空间复杂度:O(n)

3.3 分析该题目解题优势及难点。

考察学生是否熟练栈的应用
需要考虑字符的个数,若是偶数可直接将一半的字符逐个压入栈中,若是奇数则需要去除栈顶元素

posted @ 2021-04-05 22:32  黄帅2011  阅读(85)  评论(1编辑  收藏  举报