数据结构实验二

目录

问题A:子串个数

问题B:模式串

问题C:主对角线上的数据和

问题D:顺时针排螺旋阵

问题E:汉诺塔游戏中的移动

问题F:树的先根遍历

问题G:树的后根遍历


问题A:子串个数

题目描述


给你若干个字符串,请编程输出每个字符串的子串个数。
输入
若干个字符串,每个字符串占一行,字符串中不含空格,长度最大为1000。
输出
对应每一行的字符串,输出该字符串子串的个数。
样例输入 

abc
apple
software

样例输出 

7
16
37

解法1:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s;
    while (getline(cin, s))
    {
        int n = s.size(), ans = 0;
        for (int i = 0; i < n; i++) 
        {
            for (int j = i + 1; j <= n; j++) 
            {
                ans++;
            }
        }
        cout << ans+1 << endl; 
    }
    return 0;
}

解法2:

#include<iostream>
#include<string>
using namespace std;
int main()
{

  string s;
  cin>>s;
  int n=s.size();
  cout<<n*(n+1)/2+1;


}


问题B:模式串

题目描述


给你一个目标串,请查找在给目标串中是否存在模式串,存在就输出第一个模式串在目标串中出现的位置。
输入
占两行,第一行是目标串(长度小于1000),第二行为模式串(长度小于100)。
输出
输出模式串在目标串中出现的位置,即模式串匹配到目标串时第一个字符在目标串的位置(注意从1开始描述字符开始位置),不能匹配时输出0.
样例输入 

appleorange
orange


样例输出 
 

6

思路一:

#include<iostream>
#include<string>
using namespace std;
int index(string a, string b)
{
	int b_len, a_len;
	a_len = a.length();
	b_len = b.length();
	int de = 1;
	int ss = 0;
	for (int i = 0; i <= a_len-b_len; i++)
	{
		for (int j = 0; j < b_len; j++)
		{
			if (a[i + j] != b[0 + j])
			{
				de = 0;
				break;
			}
		}
		if (de == 1)
		{
			ss = i;
			break;
		}
		if (de == 0)
		{
			ss = -1;
		}
		de = 1;
	}
	return ss;
}
int main()
{
	string a, b;
	cin >> a >> b;
	int x = index(a, b);
	cout << x + 1;
}

思路二:

#include<iostream>
#include<string>
using namespace std;
int f(string s1,string s2)
{
	int len1 = s1.length();
	int len2 = s2.length();
	int ss=-1;
	for (int i = 0; i < len1; i++)
	{
		if (s1[i] == s2[0])
		{
			int x = i;
			for (int j = 0,jishu = 0; j < len2; j++, i++)
			{
				if (s1[i] == s2[j])jishu++;
				else break;
				if (jishu == len2)
				{
				   ss= x + 1;
					break;
				}
			}
		}
		
	}
	return ss;
}
int main()
{  
	string s1, s2;
	cin >> s1 >> s2;
	cout << f(s1, s2);
}

问题C:主对角线上的数据和

题目描述


在一个N行N列的方阵(或称N阶方阵)中,从左上角到右下角这一斜线上有N个数据元素,这个斜线称为方阵的主对角线。给你一个方阵,请求方阵主对角线上数据的和。
输入
第一行是N(N<100),表示下边是一个N阶方阵。接下来N行N列用空格间隔放置正整数(int型)。
输出
N阶方阵主对角线上数据的和。
样例输入 

3
1 2 3
1 2 3
1 2 3

样例输出 

6
#include<iostream>
#include<string>
using namespace std;
int main(){
	int n;
	cin>>n;
	int **A=new int*[n];//创建N行的指针数组
	for(int i = 0;i < n;i++)
		A[i] = new int[n];//对每一行,创建N个整数的数组
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			cin>>A[i][j];
		}
	}
	int sum=0;
	for(int i=0;i<n;i++){
		sum+=A[i][i];			
	}
	cout<<sum;
   for(int i=0;i<N;i++)
   {
      delete[]A[i];//释放每一行数组

   }
    
    delete A;//释放数组指针
   return 0;
}

对于C++的二维数组声明,行数和列数都要是常量表达式,不使用变量作为数组大小参数。这是因为C++的数组在编译时需要确定其大小,而变量是在运行时才会有具体的值。因此,对于输入未知行数和列数的情况,可以使用动态内存分配来创建二维数组。

问题D:顺时针排螺旋阵

题目描述

给你一个N行N列的方格矩阵,从外圈按顺时针依次填写自然数,这会构成一个螺旋阵,你能编程实现吗?
比如5行5列的情况如下:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
输入
输入一个正整数数N(N<100)。
输出
输出符合题意的螺旋阵。
样例输入 

5


样例输出 
 

1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
#include <iostream>
using namespace std;

const int maxn = 100;
int a[maxn][maxn];  // 方格矩阵
int n;  // 方格矩阵的大小

void spiral(int num, int row, int col, int len)  // num为当前数字,row和col是当前的行和列,len是剩余的绕圈长度
{
    if (len == 0) {
        return;
    }
    if (len == 1) {  // 如果剩余的绕圈长度为1,则填入当前数字并返回
        a[row][col] = num;
        return;
    }
    for (int i = 0; i < len - 1; i++) {  // 第一行
        a[row][col + i] = num;
        num++;
    }
    for (int i = 0; i < len - 1; i++) {  // 最后一列
        a[row + i][col + len - 1] = num;
        num++;
    }
    for (int i = 0; i < len - 1; i++) {  // 最后一行(倒序)
        a[row + len - 1][col + len - 1 - i] = num;
        num++;
    }
    for (int i = 0; i < len - 1; i++) {  // 第一列(倒序)
        a[row + len - 1 - i][col] = num;
        num++;
    }
    spiral(num, row+1, col+1, len-2);  // 转到内圈进行递归
}

int main()
{
    cin >> n;
    spiral(1, 0, 0, n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << a[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

问题E:汉诺塔游戏中的移动

题目描述

有三根标为A,B,C的柱子,A柱子上从上到下按金字塔状依次叠放着n个半径从1厘米到n厘米的的圆盘,要把A上的所有盘子移动到柱子C上,中间可以临时放在B上,但每次移动每一根柱子上都不能出现大盘子在小盘子上方的情况,要求用最少的移动次数完成,请编程模拟每次移动。
输入
占一行,为整数n(n<64),表示盘子数。
输出
把A上的所有盘子移动到柱子C上,每次只能移动一个盘子,输出移动每一次过程。每次移动占一行,第一个数表示第几步移动,第二个数是移动的盘子的半径,然后是从哪个柱子移动到哪个柱子。
样例输入 

2


样例输出 
 

1 1 A->B
2 2 A->C
3 1 B->C
#include <iostream>
using namespace std;
 
void move(int n,char A,char B,char C);
int step;
int main()
{
    int n;
    cin>>n;
    move(n,'A','B','C');
    return 0;
}
void move(int n,char A,char B,char C)
{
    if(n==1)
    {
        step++;
        cout<<step<<" "<<n<<" "<<A<<"->"<<C<<endl;
    }
    else
    {
        move(n-1,A,C,B);
        step++;
        cout<<step<<" "<<n<<" "<<A<<"->"<<C<<endl;
        move(n-1,B,A,C);
    }
    
}


问题F:树的先根遍历

题目描述

已知一颗树的节点间关系,请编程实现该树的先根遍历。
输入
若干行,每行描述了一组双亲节点和孩子节点的关系序偶对(每个节点用不同的大写字母表示,节点小于26个)。且树的度小于5。
输出
该树的先根遍历序列,序列中每个字母用空格隔开。
样例输入 

B E
B F
A B
A C

样例输出 

A B E F C
#include <bits/stdc++.h>//一次性引入标准库的所有头文件
using namespace std;
struct Node
 {
    vector<int> sons;
    Node(){}
}node[26];
int root = -1;
void preOrder(int root)//先根遍历函数
 {
    cout << char(root + 'A') << ' ';//先根,调换顺序可实现后根遍历
    for (int i = 0; i < node[root].sons.size(); i++)
    {
        preOrder(node[root].sons[i]);//递归
    }
}
int main() 
{
    char p, c;
    while(cin >> p >> c) //parents and children
   {
        if (p == EOF || c == EOF) break;
        node[p - 'A'].sons.push_back(c - 'A');
        if (root == c - 'A' || root == -1) 
        {
            root = p - 'A';
        }
    }
    preOrder(root);
    return 0;
}

#include <bits/stdc++.h> 是一个非标准的C++头文件引入方式,不建议在实际编程中使用。
这种方式会一次性引入标准库的所有头文件,包括iostream、vector、string、algorithm等等,方便编写代码,但是会增加编译时间和内存开销,并且不具备可移植性。本题#include<iostream>#include<vector>即可,#include <bits/stdc++.h>是一种偷懒的做法,

问题G:树的后根遍历

题目描述

已知一颗树的节点间关系,请编程实现该树的后根遍历序列。
输入
若干行,每行描述了一组双亲节点和孩子节点的关系序偶对(每个节点用不同的大写字母表示,节点小于26个)。且树的度小于5。
输出
该树的后根遍历序列,序列中每个字母用空格隔开。
样例输入 

B E
B F
A B
A C


样例输出 
 

E F B C A
#include <bits/stdc++.h>
using namespace std;
struct Node {
    vector<int> sons;
    Node(){}
}node[26];
int root = -1;
void postOrder(int root) {

    for (int i = 0; i < node[root].sons.size(); i++){
        postOrder(node[root].sons[i]);
    }
    cout << char(root + 'A') << ' ';
}
int main() {
    char p, c;
    while(cin >> p >> c) {
        if (p == EOF || c == EOF) break;
        node[p - 'A'].sons.push_back(c - 'A');
        if (root == c - 'A' || root == -1) {
            root = p - 'A';
        }
    }
    postOrder(root);
    return 0;
}

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值