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

| 这个作业属于哪个班级 | C语言--网络2011/2012 |
| ---- | ---- | ---- |
| 这个作业的地址 | DS博客作业02--栈和队列 |
| 这个作业的目标 | 学习栈和队列的结构设计及运算操作
| 名字 | 黎钊涵

0. 展示PTA总分

1.本章学习总结

1.1 栈

栈结构的定义和特点

  • 栈(stack)是一个特殊的线性表,是限定仅在一端(通常是表尾)进行插入和删除操作的线性表
  • 先进后出、后进先出
  • 插入元素到栈顶(即表尾)的操作,称为入栈
  • 从栈顶(即表尾)删除最后一个元素的操作,称为出栈
顺序栈结构体
struct SNode {
    ElementType* Data;  /* 存储元素的数组   */
    Position Top;     /* 栈顶指针 */
    int MaxSize;
};
初始化栈
void InitStack(SqStack* S)
{
   S=new SqStack;      //分配一个顺序栈空间,首地址放在S中
   S->top=-1;          //栈顶指针置为-1
}
入栈
void PushStack(Stack S, ElementType x)//入栈
{
    if (S->Top == S->MaxSize)
    {
        printf("Stack Full\n");
        return;
    }
    S->Top++;
    S->Data[S->Top] = x;
}
出栈
ElementType PopStack(Stack S)
{
    if (S->Top == -1)
    {
        printf("Stack Empty\n");
        return 0;
    }
    return S->Data[S->Top--];
}
栈空
int StackEmpty(Stack S)
{
    if (S->Top == -1)
        return 1;
    else
        return 0;
}

链栈(链栈是运算受限的单链表,插入和删除仅在栈顶处执行,头指针就是栈顶,不需要头结点,空栈相当于头指针指向空)

结构体定义
typedef int Elmetype;
struct SNode
{
	Elmetype data;
	struct SNode* next;
};
typedef struct SNode* LinkStack;
进栈
void Push(LinkStack& S, Elmetype X)
{
	LinkStack NewS = new SNode;
	/*数据载入*/
	NewS->data = X;
	/*头插法插入新数据*/
	NewS->next = S->next;
	S->next = NewS;
}
出栈
bool Pop(LinkStack& S, Elmetype& e)
{
	/*首先要判断栈顶是否为空*/
	if (S->next == NULL)
	{
		return false;
	}
	e = S->next->data;
	LinkStack delSNode = S->next;
	S->next = delSNode->next;
	delete delSNode;
	return true;
}

1.2 栈的应用

  • 数制转换
    十进制数转八进制数代码如下
public class Conversion 
{
    public static void conversion(int N) 
    {
        ArrayStack<Integer> stack = new ArrayStack<>();
        while (N != 0) 
        {
            stack.push(N % 8);
            N /= 8;
        }
        while (!stack.isEmpty()) 
        {
            System.out.print(stack.pop());
        }
    }

    public static void main(String[] args) 
    {
        conversion(2007);
    }
}
  • 括号匹配检验
    在编程过程中,如果有括号没有对应的另一半进行配对,编译器就会报错,可以用栈来实现前后括号匹配的检验,如下
public class Match 
{
    public static boolean match(String s) 
    {
        ArrayStack<Character> stack = new ArrayStack<>();
        for (int i = 0; i < s.length(); i++) 
        {
            char c = s.charAt(i);
            switch (c) 
            {
            case ')':
                if (!stack.isEmpty() && stack.pop() == '(') 
                {
                    break;
                }
                else 
                {
                    return false;
                }
            case ']':
                if (!stack.isEmpty() && stack.pop() == '[')
                {
                    break;
                }
                else 
                {
                    return false;
                }
            case '}':
                if (!stack.isEmpty() && stack.pop() == '{') 
                {
                    break;
                }
                else 
                {
                    return false;
                }
            default:
                stack.push(c);
                break;
            }
        }
        return stack.isEmpty();
    }

    public static void main(String[] args)  
    {
        System.out.println(match("{[()]()[{}]}"));
        System.out.println(match("{[()]}}"));
    }
}
  • 迷宫求解
    求迷宫从入口到出口的所有路径伪代码如下
初始化,将起点加入堆栈;
while(堆栈不为空)
{
    取出栈顶位置为当前位置;
    如果 当前位置是终点,
    则 使用堆栈记录的路径标记从起点至终点的路径;
    否则
    {
        按照从下、右、上、左的顺序将当前位置下一个可以探索的位置入栈;
        如果 当前位置的四周均不通
        则 当前位置出栈;
    }
}

1.3 队列

队列的定义和特点

  • 队列是一种先进先出的线性表。在表一端插入(队尾),在另一端(队头)删除
  • 逻辑结构:与同线性表相同,仍为一对一关系
  • 存储结构:顺序队或链队,以循环顺序队列更常见
结构体定义
typedef struct
{
    ElemType data[MaxSize];
    int front, rear;
}SqQueue;
typedef SqQueue* Queue;
初始化
void InitQueue(Queue Q)
{
    Q = (Queue)malloc(sizeof(SqQueue)*Max);
    Q->front = Q->rear = 0;
}
入队
bool EnQueue(Queue Q,ElemType e)
{
    if(Q->rear == MaxSize)
        return false;
    Q->data[Q->rear++] = e;
    return true;
}
出队
bool DeQueue(Queue Q,ElemType &e)
{
    if(Q->front == Q->rear)
        return false;
    e = Q->data[Q->front++];
    return true;
}
判断是否为空
bool QueueEmpty(Queue Q)
{
    return (Q->front == Q->rear);
}
销毁
void DestroyQueue(Queue Q)
{
    free(Q);
}

环形队列

结构体定义
typedef struct
{
    ElemType data[MaxSize];
    int front, rear;
}SqQueue;
typedef SqQueue* Queue;
初始化
void InitQueue(Queue Q)
{
    Q = (Queue)malloc(sizeof(SqQueue)*Max);
    Q->front = Q->rear = 0;
}
入队
bool EnQueue(Queue Q,ElemType e)
{
    if((Q->rear +1) % MaxSize == Q->front)
        return false;
    Q->data[Q->rear] = e;
    Q->rear = (Q->rear + 1) % MaxSize;
    return true;
}
出队
bool DeQueue(Queue Q,ElemType &e)
{
    if(Q->front == Q->rear)
        return false;
    e = Q->data[Q->front];
    Q->front = (Q->front + 1) % MaxSize;
    return true;
}
判断是否为空
bool QueueEmpty(Queue Q)
{
    return (Q->front == Q->rear);
}
销毁
void DestroyQueue(Queue Q)
{
    free(Q);
}

链式队列

结构体定义
typedef struct QNode    /* 声明链式队列的结点 */
{
    int data;
    struct QNode *next;
}Node;
typedef struct QueuePoint    /* 声明链式队列的首尾指针 */
{
    Node *front;
    Node *rear;
};
typedef QueuePoint* Queue;
初始化
Queue InitQueue (Queue Q)    
{                        
    Q = (Queue)malloc(sizeof(QueuePoint));
    Q->front = Q->rear = NULL;

    return Q;
}
入队
void EnQueue(Queue Q,ElemType e)
{
    Node* p;
    p = (Node*)malloc(sizeof(Node));
    p->data = e;
    p->next = NULL;
    if(Q->rear == NULL)
        Q->front = Q->rear = p;
    else
    {
        Q->rear->next = p;
        Q->rear = p;
    }
}
出队
bool DeQueue(Queue Q,ElemType &e)
{
    Node* p;
    if(Q->rear == NULL)
        return false;
    p = Q->front;
    if(Q->front == Q->rear)
        Q->front = Q->rear = NULL;
    else
        Q->front = Q->front->next;
    e = p->data;
    free(p);
    return true;
}
判断是否为空
bool QueueEmpty(Queue Q)
{
    return (Q->rear == NULL);
}
销毁
void DestroyQueue(Queue Q)
{
    Node* pre = Q->front,* p;
    if(pre != NULL)
    {
        p = pre->next;
        while(p != NULL)
        {
            free(pre);
            pre = p;p = p->next;
        }
        free(pre);
    }
    free(Q);
}

舞伴问题

int QueueLen(SqQueue Q)//队列长度
{
	int sum = 0;
    int i;
    for (i = Q->front + 1; i <= Q->rear; i++)//front总在数前一位
    {
        sum++;
   }
   return sum;
     //return Q->rear - Q->front;
 } 
int EnQueue(SqQueue &Q, Person e)//加入队列 
{
	if(Q->rear >= MAXQSIZE)
        return 0;
     //if(Q->rear >= MAXQSIZE) return 0;
	Q->data[Q->rear++] = e;
	return 1;
} 
int QueueEmpty(SqQueue &Q)//队列是否为空 
{
	return (Q->front == Q->rear);
}
int DeQueue(SqQueue &Q, Person &e)//出队列 
{
	if(QueueEmpty(Q))
        return 0;
	e = Q->data[Q->front++];
	return 1;
}
void DancePartner(Person dancer[], int num) //配对舞伴 
{
	Person male,female;
	int i;
     //将男生女生数组全部入队
	for(i = 0; i < num; i ++)
    {
		
		if(dancer[i].sex == 'F')
			EnQueue(Fdancers,dancer[i]);
		else 
			EnQueue(Mdancers,dancer[i]); 
	}
	while(QueueLen(Fdancers) != 0 && QueueLen(Mdancers) != 0)
    {
		DeQueue(Fdancers,male);
		cout<<male.name<<"  ";
		DeQueue(Mdancers,female);
		cout<<female.name <<endl;
	} 
}

2.PTA实验作业

2.1 符号配对(本题用C++作答,此段代码用C则编译错误)

#include<iostream>
#include<cstdlib>
using namespace std;
//#define ERROR NULL
const int MaxSize=109;
typedef char ElementType;

struct Stack{
    ElementType Symbol[MaxSize];
    int Top;
};

Stack* Create();
bool Push(Stack* S,ElementType X);
ElementType Pop(Stack* S);
ElementType getTop(Stack* S);///获取栈顶元素

int main()
{
    Stack* S=Create();
    char str[1000],stacktop;
    int i,flag=0,flag2=0,flag_i=0;
    while(true)
    {
        cin.getline(str,1000);  ///用gets发生编译错误
        if(str[0]=='.') 
            break;///一行一行地读取,遇到'.'时结束
        for(i=0;str[i]!='\0';i++)
        {
            flag_i=0;
            /** 遇到左符号,入栈*/
            if(str[i]=='('||str[i]=='['||str[i]=='{')
                Push(S,str[i]);
            if(str[i]=='/'&&str[i+1]=='*')
            {
                flag_i=1;///遇到/*的标志
                Push(S,str[i]);
                Push(S,str[i+1]);
            ///    i++; 若在此处使i++,则下面的if语句中i值被改变
            }
            /** 遇到右符号,与栈顶符号配对*/
            if(str[i]==')')
            {
                if(S->Top==-1)///栈为空,则当前右符号缺少左符号,结束循环
                {
                    cout<<"NO"<<endl;
                    cout<<"?-"<<str[i]<<endl;
                    flag=1;///栈空时判断是否YES的标志
                    flag2=1;///跳出while循环的标志
                    break;
                }
                stacktop=getTop(S);
                if(stacktop!='(')///栈顶元素与当前右符号不匹配,结束循环
                {
                    flag2=1;
                    break;
                }
                else
                    Pop(S); ///匹配则出栈
            }
            if(str[i]==']')
            {
                if(S->Top==-1)
                {
                    cout<<"NO"<<endl;
                    cout<<"?-"<<str[i]<<endl;
                    flag=1;
                    flag2=1;
                    break;
                }
                stacktop=getTop(S);
                if(stacktop!='[')
                {
                    flag2=1;
                    break;
                }
                else
                    Pop(S);
            }
            if(str[i]=='}')
            {
                if(S->Top==-1)
                {
                    cout<<"NO"<<endl;
                    cout<<"?-"<<str[i]<<endl;
                    flag=1;
                    flag2=1;
                    break;
                }
                stacktop=getTop(S);
                if(stacktop!='{')
                {
                    flag2=1;
                    break;
                }
                else
                    Pop(S);
            }
            if(str[i]=='*'&&str[i+1]=='/')
            {
                if(S->Top==-1)
                {
                    cout<<"NO"<<endl;
                    cout<<"?-*/"<<endl;
                    flag=1;flag2=1;
                    break;
                }
                stacktop=getTop(S);
                if(stacktop!='*')
                {
                    flag2=1;
                    break;
                }
                else
                {
                    Pop(S);
                    Pop(S);
                }
                i++;/// */比较完毕后i同样++
            }
            if(flag_i)
                i++;/// 缺少该语句将使 /*/ 被判定为配对成功
        }
        if(flag2)
            break;
    }
    if(S->Top!=-1)///栈不空,则栈顶元素缺少右符号
    {
        cout<<"NO"<<endl; ///YES NO 注意大写
        if(getTop(S)=='*')
            cout<<"/*-?"<<endl;
        else
            cout<<Pop(S)<<"-?";
    }
    else if(!flag)///栈空且flag==0,全部配对成功
        cout<<"YES";

    system("pause");
    delete S;
    
    return 0;
}

Stack* Create()
{
    Stack* S=new Stack;
    S->Top=-1;
    return S;
}

bool Push(Stack* S,ElementType X)
{
    if(S->Top==MaxSize-1)
        return false;
    S->Symbol[++(S->Top)]=X;
    return true;
}

ElementType Pop(Stack* S)
{
   // if(S->Top==-1)
      //  return ERROR;
    return S->Symbol[(S->Top)--];
}

ElementType getTop(Stack* S)
{
    ElementType top=Pop(S);
    Push(S,top);
    return top;
}

2.1.1解题思路及伪代码

把比较特殊的/和/用< >代替,创建一个栈然后把找到的对应符号放入栈中,然后进行比较得到符号是否匹配

int main
{
  static char ch1[1000], ch2[1000], ch[10000];//ch放代码,ch2放找到的符号,ch1用于符号匹配
for(i = 0;; i++)
  {
    找到对应符号然后放入ch2中//用<>代替两个的符号
  }
int flag=1 用于记录
for (i = 0; i < k; i++)
  {
    if ch2中符号是左符号,放入栈中
    else if ch2中符号是右符号
    {
      if 栈中存在符号,并且和ch2和栈中符号匹配,则消除栈中该符号
      else 输出NO 和对应缺少的符号,flag=0
    }
  }
if flag=1同时栈中无符号 输出YES
else
  {  输出  NO
     根据栈中情况输出对应缺少符号
  }
}

2.1.2总结解题所用的知识点

  • 顺序栈的结构
  • 顺序栈的出栈入栈操作
  • 递归函数的调用
  • 标准输入输出流的运用

2.2 银行业务队列简单模拟

2.2.1 解题思路及伪代码

思路

伪代码

输入人数k
创建队列q,p
for (i = 0; i < k; i++)
{
    cin >> n;//输入编号
    if (n % 2)  编号为奇数则入奇数的栈;
    else  编号为偶数则入偶数的栈	;
}
for (i = 0; i < k; i++)
{
	if (i == 0)//对第一个数据输出处理空格
	if ((i + 1) % 3)//对a窗口处理
	{
		if (!q1.empty()//判断是否处理完毕
                        未处理完毕打出a窗口的编号;
	        else 处理完毕直接打出b窗口的所有编号;	
	}
	else//对b窗口处理
	{
		if (!q2.empty())//判断是否处理完毕
                        未处理完毕打出b窗口的编号
		else 处理完毕直接打出b窗口的所有编号
	}
}
    return 0;
}

2.2.2 总结解题所用的知识点

  • 学会运用queue容器。
  • 掌握了队列的创建,判空,入队,出队等操作
  • 懂得了对两个队列的判断,当A或B两个有一个队列为空就退出循环,然后单独输出剩余队列

3.阅读代码

3.1 题目及解题代码

Stack CreateStack(int MaxSize)//双栈结构即为两个栈共享一块空间
{
    Stack stack = (struct SNode *)malloc(sizeof(struct SNode));//先为栈分配一个空间
    stack->Data = (int *)malloc(sizeof(ElementType)* MaxSize);//为栈分配一个Macsize大小的数组空间存放值
    stack->Top1 = -1;//栈1空
    stack->Top2 = MaxSize;//栈2空
    stack->MaxSize = MaxSize;//
    return stack;
}

bool Push(Stack S, ElementType X, int Tag)//入栈操作
{
    if (!S)//这个栈空间不存在,分配失败的时候
        return false;
    if (S->Top1+1==S->Top2)//栈满的情况
    {
        printf("Stack Full\n");
        return false;
    }

    if (Tag == 1)
       
        S->Data[++S->Top1] = X;//++在前先取数据使用后自加
 
     else 
         S->Data[--S->Top2] = X;

     return true;
}

ElementType Pop(Stack S, int Tag)
{
    if (!S)
        return ERROR;
    if (Tag == 1)
    {
        if (S->Top1 == -1)//空栈时
        {
            printf("Stack %d Empty\n",Tag);
            return ERROR;
        }
        return S->Data[S->Top1--];//出栈top1向前移动
    }
    
    if (S->Top2 == S->MaxSize)
    {
        printf("Stack %d Empty\n", Tag);
        return ERROR;
    }
    return S->Data[S->Top2++];//出栈top2向后移动
    
}

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

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

posted @ 2021-06-30 20:06  走去干饭  阅读(73)  评论(0编辑  收藏  举报