浙大版《数据结构(第2版)》题目集编程题题解

编程题

先放个地址题目链接:https://pintia.cn/problem-sets/434/problems/type/6感谢免费开放题集
函数题链接:https://blog.csdn.net/Alpaca00/article/details/104417403

使用的语言在c++和c之间跳跃,其实也没差

实例1.1 最大子列和问题 (20分)

这是一个很经典的问题,可以考虑的是当前的连续和如果比0小了,就贪心的舍弃掉,否则和答案进行比较
(很皮的写了一下c++)

#include
using namespace std;
int main()
{
    int n;
    int t;
    int sum=0;
    int ans=0;
    cin>>n;
    while(n--){
        cin>>t;
        sum+=t;
        if(ans<sum) ans=sum;
        if(sum<0) sum=0;
    }
    if(ans<sum) sum=ans;
    cout<<ans<<endl;
    return 0;
}

习题2.1 简单计算器 (20分)

模拟题

#include
using namespace std;
int main()
{
    int ans;
    int num;
    char ch;
    cin>>ans;
    while(cin>>ch&&ch!='='){
        cin>>num;
        switch(ch){
            case '+':
                ans+=num;
                break;
            case '-':
                ans-=num;
                break;
            case '*':
                ans*=num;
                break;
            case '/':
                if(num==0){
                    cout<<"ERROR"<<endl;
                    return 0;
                }else{
                	ans/=num;
				}
                break;
            default:
                cout<<"ERROR"<<endl;
                return 0;
                break;
        }
    }
    cout<<ans<<endl;
    return 0;
}

习题2.2 数组循环左移 (20分)

说是左移但是实际上可以输出后面一部分在输出前面一部分,记得加个求余就行了

#include
int main()
{
    int num[105];
    int n,m;
    scanf("%d %d",&n,&m);
    int i;
    for(i=0;i<n;i++){
        scanf("%d",num+i);
    }
    m%=n;
    int flag=0;
    for(i=m;i<n;i++){
        if(flag) printf(" ");
        printf("%d",num[i]);
        flag=1;
    }
    for(i=0;i<m;i++){
        if(flag) printf(" ");
        printf("%d",num[i]);
        flag=1;
    }
    return 0;
}

习题2.3 数列求和-加强版 (20分)

从后往前加那就是最后一位一直乘,有多少个A就乘多少个A就好了,之后直接求余进位
还要处理下最高位的数字直接输出

#include
int main()
{
    char ans[100010];
    int a,n;
    int i;
    int t1,t2;
    int cnt;
    scanf("%d %d",&a,&n);
    if(n==0) printf("0");
    cnt=t2=0;
    for(i=n;i>=1;i--){
        t1=t2+i*a;
        ans[cnt++]=t1%10+'0';
        t2=t1/10;
    }
    if(t2) printf("%d",t2);		//最高位数字
    for(i=cnt-1;i>=0;i--){
    	putchar(ans[i]);
	}
	printf("\n");
    return 0;
}

习题2.8 输出全排列 (20分)

就是最常见的dfs
不会的话可以先学习一下dfs

#include
int n;
int vis[10];
char s[15];
void dfs(int a)
{
	if(a>n){
		s[n+1]='\0';
		printf("%s",s+1);
		printf("\n");
		return ;
	}
	int i;
	for(i=1;i<=n;i++){
		if(!vis[i]){
			s[a]=i+'0';
			vis[i]=1;
			dfs(a+1);
			vis[i]=0;
		}
	}
}
int main()
{
    scanf("%d",&n);
    dfs(1);
    return 0;
}

习题3.4 最长连续递增子序列 (20分)

就是直接循环找一遍就行了
可以数组从1开始存储,第0个元素存一个最小值(比如0),这样方便判断
然后还要注意最后出来的时候一直都是递增的,所以循环结束后要加个判断

#include
int num[100005];
int main()
{
	int n;
	int count,ans;
	int start,end;
	int i;
	count=ans=0;
	scanf("%d",&n);
	num[0]=0;
	for(i=1;i<=n;i++){
		scanf("%d",num+i);
		if(num[i]>num[i-1]){
			count++;
		}else{
			if(count>ans){
				ans=count;
				start=i-count;
				end=i-1;
			}
			count=1;
		}
	}
	if(count&&count>ans){
		start=n-count+1;
		end=i-1;
	}
	for(i=start;i<=end;i++){
		if(i!=start) printf(" ");
		printf("%d",num[i]);
	}
    return 0;
}

习题3.6 一元多项式的乘法与加法运算 (20分)

待补充

习题3.8 符号配对 (20分)

这题是个栈的裸题,就是左括号进,右括号出,和栈顶比较看看是否配对,不好匹配的是/*需要自己想办法
但是我写的比较乱所以最好不要参考

#include
#include
char s[105];
char stack[1005];
int main()
{
	int i,j;
	int n;
	int len;
	char s1[4]={'/','(','[','{'};
	char s2[4]={'/',')',']','}'};
	int top=0;
	int flag=1;
	while(1){
		gets(s);
		len=strlen(s);
		if(len==1&&s[0]=='.') break;
		for(i=0;i<len;i++){
			if(s[i]=='/'&&s[i+1]=='*'){
				stack[top++]=s[i];
				i++;
				continue;
			}
			if(s[i]=='*'&&s[i+1]=='/'){
				if(top==0||stack[top-1]!='/'){
					flag=0;
				}else{
					i++;
					top--;
					continue;
				}
			}
			if(flag==0) break;
			for(j=1;j<4;j++){
				if(s1[j]==s[i]){
					stack[top++]=s[i];
					break;
				}
				if(s2[j]==s[i]){
					if(top==0||stack[top-1]!=s1[j]){
						flag=0;
					}else top--;
					break;
				}
			}
			if(flag==0) break;
		}
		if(flag==0) break;
	}
	if(flag){
		if(top==0) printf("YES\n");
		else{
			printf("NO\n");
			if(stack[top-1]=='/') printf("/*-?\n");
			else printf("%c-?\n",stack[top-1]);
		}	
	}else{
		printf("NO\n");
		if(top!=0){
			if(stack[top-1]=='/') printf("/*-?\n");
			else printf("%c-?\n",stack[top-1]);
		}else{
			if(s[i]=='*') printf("?-*/\n");
			else printf("?-%c\n",s[i]);
		}
	}
    return 0;
}

习题3.9 堆栈操作合法性 (20分)

和函数题里面的栈一样的题

#include
#include
int main()
{
	char s[105];
	int n,m;
	int len;
	int top;
	int flag;
	int i;
	scanf("%d %d",&n,&m);
	while(n--){
		scanf("%s",s);
		len=strlen(s);
		top=0;
		flag=1;
		for(i=0;i<len;i++){
			if(s[i]=='S'){
				top++;
			}else{
				top--;
			}
			if(top>m||top<0){
				flag=0;
				break;
			}
		}
		if(flag&&!top) printf("YES\n");
		else printf("NO\n");
	}	
	return 0;
}

习题3.10 汉诺塔的非递归实现 (25分)

汉诺塔递归形式怎么理解可以自己先写在纸上模拟几次看看怎么执行才能完成
然后就会发现是要移动这个塔,得先移动掉上面的部分到用来辅助的棍子上,然后再把最下面的移动到目标位置,接着再把辅助位置上的移动到目的地。如此往复,就形成了一个递归,可以看代码,比较清晰,就是这几句话的翻译而已。
这个就得先写出汉诺塔的递归形式,然后再把函数和未执行的语句做个标记一个个入栈来模拟递归就行了

#include
#include
void f_hanoi(int n,char from,char sup,char to)
{
	if(n==1){
		printf("%c->%c\n",from,to);
		return ;
	}
	f_hanoi(n-1,from,to,sup);
	printf("%c->%c\n",from,to);
	f_hanoi(n-1,sup,from,to);
}								//递归版
typedef struct node{
	int n;
	char from,sup,to;
	int flag;
}hanoi;							//用结构体来模拟函数参数
int main()
{
	hanoi stack[10000];
	int n;
	int top=0,start=0;
	scanf("%d",&n);
	struct node in,out;
	in.n=n;
	in.from='a';
	in.sup='b';
	in.to='c';
	in.flag=0;
	stack[top++]=in;
	while(top!=0){
		out=stack[--top];
		if(out.flag==1){
			printf("%c -> %c\n",out.sup,out.to);
		}
		if(out.n==1){
			printf("%c -> %c\n",out.from,out.to);
			continue;
		}
		in.n=out.n-1,in.from=out.sup,in.sup=out.from,in.to=out.to;
		in.flag=1;
		stack[top++]=in;		//注意先进栈的是后面那句话f_hanoi(n-1,sup,from,to);
		in.n=out.n-1,in.from=out.from,in.sup=out.to,in.to=out.sup;
		in.flag=0;
		stack[top++]=in;
	}
	//f_hanoi(n,'a','b','c');
	return 0;
}

习题3.11 表达式转换 (25分)

这个题非常坑,要注意既有负数或者正数带个多余的+号又有小数
其他就是没啥了,中缀转后缀就是一个栈操作,具体可以百度。
我的代码也是别参考,这题有点乱写的。

练习4.1 根据后序和中序遍历输出先序遍历 (25分)

也是裸题,做法就是根据后序是根在最后,所以从后往前读后序数组每个都当做一个根,然后再根据(左根右的中序来确定每个节点的位置)

#include
int l[35],r[35];
int k1[35],k2[35];  //后序和中序
int cnt;
int n;
int find(int start,int end)
{
	int i;
	int t=cnt;
	for(i=start;i<=end;i++){
		if(k2[i]==k1[cnt]){		//k1反过来读当做先序遍历 
			cnt--;
			r[t]=find(i+1,end);
			l[t]=find(start,i-1);
			break;
		}
	}
	if(i>end) return 0;
	else return t;
}
void pri(int i)
{
	if(i!=0){
		printf(" %d",k1[i]);
		pri(l[i]);
		pri(r[i]);
	}
}
int main()
{
	int i;
	scanf("%d",&n);
	cnt=n;
	for(i=1;i<=n;i++) scanf("%d",k1+i);
	for(i=1;i<=n;i++) scanf("%d",k2+i);
	find(1,n);
	printf("Preorder:");
	pri(n);
	return 0;
}

练习4.2 平衡二叉树的根 (25分)

待学习AVL树

练习4.3 堆中的路径 (25分)

二叉堆的裸题,每次只要除2往上找就行了

#include
int heap[1025];
int n;
int end;
void pri(int ind)
{
	int flag=0;
	while(ind!=0){
		if(flag) printf(" %d",heap[ind]);
		else printf("%d",heap[ind]),flag=1;
		ind>>=1;
	}
}
void push(int num)
{
	int ind=end>>1,last_ind=end;
	while(ind!=0&&heap[ind]>num){
		heap[last_ind]=heap[ind];
		last_ind=ind;
		ind>>=1;
	}
	heap[last_ind]=num;
	end++;
}
int main()
{
	int m;
	int num;
	end=1;
	scanf("%d %d",&n,&m);
	while(n--){
		scanf("%d",&num);
		push(num);
	}
	while(m--){
		scanf("%d",&num);
		pri(num);
		printf("\n");
	}
	return 0;
}

未完待续…

你可能感兴趣的:(题解)