数据结构实验第六周

6-1 在一个数组中实现两个堆栈

原理就是共享栈,不会的可以看我的数据结构博客

Stack CreateStack (int MaxSize)
{
    Stack S=(Stack)malloc(sizeof(struct SNode));//这个初始化记得写
    S->Top1=-1,S->Top2=MaxSize;//栈满的条件
    S->MaxSize=MaxSize;
    S->Data=(int*)malloc(sizeof(int)*MaxSize);//还有申请空间
    return S;
}

bool Push(Stack S,ElementType X,int Tag)
{
    if(S->Top2-S->Top1==1) {
        printf("Stack Full\n");//记得写这几个
        return false;
    }
    else{
        if(Tag==1){
           S->Data[++(S->Top1)]=X;//入队符号在前面,出队符号放后面
        }
        if(Tag==2){
            S->Data[--(S->Top2)]=X;
        }
        return true;
    }
 
}

ElementType Pop(Stack S,int Tag)
{
    if(Tag==1) {
        if(S->Top1==-1) {
            printf("Stack 1 Empty\n");//记得写
            return ERROR;
        }
        else return S->Data[(S->Top1)--];
    }
    else {
        if(S->Top2==S->MaxSize){
         printf("Stack 2 Empty\n");   //记得写
         return ERROR;
        }
        else return S->Data[(S->Top2)++];
    }
    

}

6-2 带头结点的链队列的基本操作

用链表来模拟队列,front一直指向头结点,rear随着元素的入队而移动,元素入队就是在尾结点后面插入元素,出队就是删除头结点后的这个元素

Status QueueInsert(LinkQueue *Q, ElemType e) {
	LinkList p;
	p = (LNode *)malloc(sizeof (LNode )); //创建新结点
	p->data = e; //赋值
	p->next = NULL; //插入的结点总是为最后一个结点
	//下面两步为尾插法
	(*Q).rear->next = p;
	(*Q).rear = p;
	return 1;

}

Status QueueDelete(LinkQueue *Q, ElemType *e) {
	if ((*Q).rear == (*Q).front ) return ERROR; //如果是空队列
	//队头和队尾都指向头结点
	LNode *p = (*Q).front->next;

	*e = p->data; //这里要加星号 *e,没写就错

	//出队就是把头结点后的那个结点释放掉
	(*Q).front->next = p->next;
	if ((*Q).rear == p) (*Q).rear = (*Q).front; //原队列只有一个结点,删除后变空
	free(p);
	return OK;
}

7-1 表达式求值

遇到数字就入栈,遇到操作符就取出栈顶的两个数字进行计算,注意是栈顶第一个为符号右边的数,第二个为符号左边的数,计算完然后再放入栈中,直到栈最后剩一个元素就是答案

#include <bits/stdc++.h>
using namespace std;

int main()
{
   
    string s;
      while(cin>>s)//多组输入
      {
          double ans;
          stack<double >st;
          int n=s.size();
        for(int i=0;i<n;i++)
        {
            if(isdigit(s[i])) st.push(s[i]-'0');//数字入栈,注意转化
            else{
                if(st.size()){
                    double r=st.top();//第一个数为符号右边的数
                    st.pop();
                    double l=st.top();//第二个数为左边的数
                    st.pop();
                    //根据符号,算完入栈
                    if(s[i]=='+') st.push(l+r);
                    if(s[i]=='-') st.push(l-r);
                    if(s[i]=='*') st.push(l*r);
                    if(s[i]=='/') st.push(1.0*l/r);
                }
               
            }
            
        }
          ans=st.top();
          printf("%.2lf\n",ans);
      }
    

    
}

7-2 求解迷宫从入口到出口的路径

dfs+记录路径
注意题目说的 要按照右下左上的顺序来搜索,所以dx,dy要按相应顺序写
解法1:

#include<bits/stdc++.h>
using namespace std;
int Map[20][20];
stack<pair<int,int> >q;
int bj;
int xi[5] = {0,0,1,0,-1};
int yi[5] = {0,1,0,-1,0};
int n;
int vis[20][20];
void dfs(int x,int y){
    if( x == n-2 && y == n-2 ){
        bj = 1;
        return ;
    }
    for(int i = 1;i <= 4; ++i){
        int xx = x+xi[i];
        int yy = y+yi[i];
        if( xx >= 1 && x <= n-2 && yy >= 1 && yy <= n-2 && !vis[xx][yy] && !Map[xx][yy] ){
            vis[xx][yy] = 1;
            dfs(xx,yy);//dfs走到终点以后,也就是递归中的递,然后不断返回到每一步,把坐标放进栈里。
            if( bj ){
                q.push({xx,yy});
                return ;
            }
            vis[xx][yy] = 0;
        }
    }
}
int main()
{
    cin >> n;
    for(int i = 0;i < n; ++i){
        for(int j = 0;j < n; ++j)cin >> Map[i][j];
    }
    vis[1][1] = 1;
    dfs(1,1);
    q.push({1,1});
    if( bj ){
        while( !q.empty() ){
            cout << "(" << q.top().first << "," << q.top().second << ")" ;q.pop();
        }
        cout << endl;
    }
    else cout << "NO" << endl;
    return 0; 
}

解法2:

开两个数组,一个用来存当前路径下每个距离的坐标,一个用来存更新后的坐标

#include <bits/stdc++.h>
using namespace std;
//swj
char c[15][15];
int vis[15][15];
int n;
int dx[] = {0, 1, 0, -1};//方向数组
int dy[] = {1, 0, -1, 0};//方向数组
int minn = 1e9;
int pre[105][2];//记录移动距离为i的每个坐标(x,y)
int ans[105][2];


int flag = 0;
void dfs(int x, int y, int sum) {
	//swjswjswj swj swj
	if (x == n - 2 && y == n - 2) {
		flag = 1;
		minn = min(minn, sum);
		memset(ans, 0, sizeof ans);//把ans全赋值为0
		for (int i = 1; i < minn; i++) {
			ans[i][0] = pre[i][0];
			ans[i][1] = pre[i][1];
		}
	
		return;
	}

	for (int i = 0; i < 4; i++) {//每个dfs的for循环让其从右下左上来搜
		int nx = x + dx[i], ny = y + dy[i];
		if (!vis[nx][ny] && c[nx][ny] == '0' && nx > 0 && nx < n - 1 && ny > 0 && ny < n - 1) {
			//走过的标记一下,并且要在范围内走
			pre[sum][0] = nx;
			pre[sum][1] = ny;
			vis[nx][ny] = 1;
			dfs(nx, ny, sum + 1);//接着走
		}

	}

}



int main() {
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) cin >> c[i][j];

	vis[1][1] = 1;
	dfs(1, 1, 1);
	ans[0][0] = ans[0][1] = 1;
	if (flag) for (int i = 0; i < minn; i++) printf("(%d,%d)", ans[i][0], ans[i][1]);
	else cout << "NO";
	return 0;

}


7-3 银行业务队列简单模拟
开两个队列,一个放奇数,一个放偶数,然后按题意输出

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int n;
    cin>>n;
    vector<int>ve(n);
    for(int i=0;i<n;i++) cin>>ve[i];
    queue<int>a,b;
    for(int i=0;i<n;i++)
    {
        if(ve[i]&1) a.push(ve[i]);
        else b.push(ve[i]);
    }

    vector <int>ans;
    while(a.size()&&b.size())//这样条件保证了人数少的输出完就跳出循环
    {
        ans.push_back(a.front());
        a.pop();
        if(a.size()) ans.push_back(a.front()) ,a.pop();//可能输出一个后A就输出完了
        ans.push_back(b.front());
        b.pop();
    }

    //看哪个还有没输出的 把他们输出出来
    while(a.size()){
        ans.push_back(a.front());
        a.pop();
    }
    while(b.size())
    {
        ans.push_back(b.front());
        b.pop();
    }
    cout<<ans[0];
    for(int i=1;i<ans.size();i++) cout<<" "<<ans[i];
    
}

posted on 2024-10-11 15:21  swj2529411658  阅读(18)  评论(0编辑  收藏  举报

导航