ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JLU数据结构上机实验2

2021-05-17 20:02:16  阅读:166  来源: 互联网

标签:JLU head 上机 int next ++ num 数据结构 data


7-1 数列查询

原题呈现:
在这里插入图片描述

解题思路: 该题时间给的比较紧,只有10ms,因而用打表的方法解决。

以下是根据这一思路写出的代码:

#include <stdio.h>
#include <malloc.h>
#include <string.h>

long long a[10000];

int main() {
	a[0] = 10;
	int n,x;
	scanf("%d", &n);
	for (int i = 1; i < 10000; i++) {
		a[i] = a[i - 1] * 11 / 10;
	}
	for (int i = 0; i < n; i++) {
		scanf("%d", &x);
		printf("%d\n", a[x-1]);
	}

	return 0;
}

解后反思: 由于题目给出查询的值在int范围内,因而可以算出自变量的上限:由10*(11/10)n<231,可求出n<203,也就是自变量的上限为202。

7-2 稀疏矩阵之和

原题呈现:
在这里插入图片描述

解题思路: 用三元组存储稀疏矩阵。首先判断两个矩阵行、列数是否相等(即是否可以相加)。然后比较非零数值所在的行数、列数大小,以此决定将其中的哪一个放入表示结果的三元组(比较及分类讨论过程详见代码注释)。

以下是根据这一思路写出的代码:

#include <stdio.h>

#define MaxSize 50000//矩阵中非零元素最多个数
typedef struct
{
	int r;			//行数
	int c;			//列数
	int d;			//数据元素
}TupNode;			//三元组定义

typedef struct
{
	int row;				//行数值
	int cols;				//列数值
	int nums;				//非零元素个数
	TupNode data[MaxSize];	//存放数组
}TSMatrix;					//三元组顺序表定义

//输出三元组
void DipMat(TSMatrix t)
{
	int i;
	printf("%d %d %d\n", t.row, t.cols, t.nums);
	if (t.nums <= 0)//判断是否有非零元素
		return;	
	for (i = 0; i < t.nums; i++)
		printf("%d %d %d\n", t.data[i].r, t.data[i].c, t.data[i].d);
}

//两个稀疏矩阵相加后对应的三元组
void MatAdd(TSMatrix a, TSMatrix b, TSMatrix& c)
{
	if (a.row != b.row || a.cols != b.cols)//判断是否符合矩阵相加条件,即两矩阵行数和列数分别相等
	{
		printf("Illegal!");
		return;
	}
	c.row = a.row;						//总行数赋值
	c.cols = a.cols;					//总列数赋值
	int i = 0, j = 0, k = 0;
	while (i < a.nums || j < b.nums)		//遍历两个三元组
	{
		if (i < a.nums && j < b.nums && a.data[i].r < b.data[j].r)//比较非零数值所在的行数大小,将较小的行数的非零数值放进c的三元组
		{
			c.data[k].r = a.data[i].r;
			c.data[k].c = a.data[i].c;
			c.data[k].d = a.data[i].d;
			i++;
			k++;
		}
		else if (i < a.nums && j < b.nums && a.data[i].r == b.data[j].r)//比较非零数值所在的行数大小,相等时
		{
			if (a.data[i].c < b.data[j].c)//比较非零数值所在的列数大小,将较小的列数非零数值放进c的三元组
			{
				c.data[k].r = a.data[i].r;
				c.data[k].c = a.data[i].c;
				c.data[k].d = a.data[i].d;
				i++;
				k++;
			}
			else if (i < a.nums && j < b.nums && a.data[i].c == b.data[j].c)//比较非零数值所在的列数大小,将两个非零元素相加的值放进c的三元组
			{
				c.data[k].r = b.data[j].r;
				c.data[k].c = b.data[j].c;
				c.data[k].d = a.data[i].d + b.data[j].d;
				i++;
				j++;
				if (c.data[k].d != 0)
				k++;
			}
			else if (i < a.nums && j < b.nums)							//比较非零数值所在的列数大小,将较小的列数非零数值放进c的三元组
			{
				c.data[k].r = b.data[j].r;
				c.data[k].c = b.data[j].c;
				c.data[k].d = b.data[j].d;
				j++;
				k++;
			}
		}
		else if (i < a.nums && j < b.nums)							//比较非零数值所在的行数大小,将较小的行数数非零数值放进c的三元组
		{
			c.data[k].r = b.data[j].r;
			c.data[k].c = b.data[j].c;
			c.data[k].d = b.data[j].d;
			j++;
			k++;
		}
		else if (i == a.nums) {
			c.data[k].r = b.data[j].r;
			c.data[k].c = b.data[j].c;
			c.data[k].d = b.data[j].d;
			j++;
			k++;
		}
		else if (j == b.nums) {
			c.data[k].r = a.data[i].r;
			c.data[k].c = a.data[i].c;
			c.data[k].d = a.data[i].d;
			i++;
			k++;
		}
	}
	c.nums = k;//非零元素个数
}

//返回三元组 t 表示的 A[i][j]值
int getvalue(TSMatrix t, int i, int j)
{
	for (int k = 0; k < t.nums; k++)
	{
		if (t.data[k].r == i && t.data[k].c == j)
			return t.data[k].d;
	}
	return 0;
}


int a[1000][1000], b[1000][1000];

int main()
{
	TSMatrix t1, t2, c;			//t1, t2为三元组

	int tmpr, tmpc, tmpd, tmpnumber = 0, sum;

	scanf("%d %d %d", &t1.row, &t1.cols, &sum);
	for(int i = 0; i < sum; i++) {
		scanf("%d %d %d", &tmpr, &tmpc, &tmpd);
		if (tmpr > t1.row) {
			printf("Illegal!");
			return 0;
		}
		t1.data[tmpnumber].r = tmpr;
		if (tmpr > t1.cols) {
			printf("Illegal!");
			return 0;
		}
		t1.data[tmpnumber].c = tmpc;
		t1.data[tmpnumber].d = tmpd;
		tmpnumber++;
	}
	t1.nums = tmpnumber;
	tmpnumber = 0;

	scanf("%d %d %d", &t2.row, &t2.cols, &sum);
	for (int i = 0; i < sum; i++) {
		scanf("%d %d %d", &tmpr, &tmpc, &tmpd);
		t2.data[tmpnumber].r = tmpr;
		t2.data[tmpnumber].c = tmpc;
		t2.data[tmpnumber].d = tmpd;
		tmpnumber++;	
	}
	t2.nums = tmpnumber;
	tmpnumber = 0;

	MatAdd(t1, t2, c);			//计算两个稀疏矩阵相加后对应的三元组
	DipMat(c);					//输出三元组

	return 0;
}

解后反思: 博主在上机时没有考虑到两个矩阵对应位置的加和可能为0,在这种情况下就不用把和保存在三元组中。这道题本身不算很难,但需要考虑的点比较多。

7-3 文字编辑

原题呈现:
在这里插入图片描述
错误解题思路: 用循环链表保存数据并通过对循环链表的操作模拟题中的各个过程。

以下是根据错误解题思路写出的代码:

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <iostream> 
using namespace std;

typedef struct x {
	int num;
	struct x* next;
}xtype;
typedef xtype* pxtype;
pxtype head, rear, p, p0, q, q0;

int main() {
	int t, n, m, i, j;
	int k, kk;
	char s;
	scanf("%d", &t);
	for (k = 0; k < t; k++) {
		scanf("%d %d", &n, &m);
		for (kk = 0; kk < n; kk++) {
			pxtype p;
			p = (pxtype)malloc(sizeof(xtype));
			p->num = kk + 1;
			if (kk == 0) {
				head = p;
				rear = p;
				p->next = head;
			}
			else {
				rear->next = p;
				rear = p;
				p->next = head;
			}
		}
		p0 = head;
		p = head;
		q0 = head;
		q = head;

		for (kk = 0; kk < m; kk++) {
			p0 = head;
			p = head;
			q0 = head;
			q = head;
			char ch;
			while ((ch = getchar()) != '\n' && ch != EOF) {};
			scanf("%c %d %d", &s, &i, &j);
			if (s == 'A') {
				while (p->num != i) {
					p0 = p;
					p = p->next;
				}
				if (p == head){
					head = head->next;
					q0 = head;
					q = head;
				}
				p0->next = p->next;
				free(p);
				while (q->num != j) {
					q0 = q;
					q = q->next;
				}
				pxtype newp;
				newp = (pxtype)malloc(sizeof(xtype));
				newp->num = i;
				q0->next = newp;
				newp->next = q;
			}
			else if (s == 'B') {
				while (p->num != i) {
					p0 = p;
					p = p->next;
				}
				if (p == head) {
					head = head->next;
					q0 = head;
					q = head;
				}
				p0->next = p->next;
				free(p);
				while (q->num != j) {
					q0 = q;
					q = q->next;
				}
				q0 = q;
				q = q->next;
				pxtype newp;
				newp = (pxtype)malloc(sizeof(xtype));
				newp->num = i;
				q0->next = newp;
				newp->next = q;
			}
			else if (s == 'Q') {
				while (p->num != j) {
					p0 = p;
					p = p->next;
				}
				if (i == 0)
					printf("%d\n", p0->num);
				else if (i == 1)
					printf("%d\n", p->next->num);
			}
		}
	}

	return 0;
}

错因分析: 每次需要定位一个字符时都需要从头开始遍历,时间复杂度过高。

改进版解题思路: 用双向循环链表保存数据,为了写起来简便采取静态链表形式。用类似“跳舞”的方法模拟题目中的移动操作。

以下是根据这一思路写出的代码:

#include <stdio.h>

int left[10000], right[10000];

int main() {
	int t; 
	scanf("%d", &t);
	for(int k=0;k<t;k++) {
		int n, q; 
		scanf("%d %d", &n, &q);
		for (int kk = 1; kk <= n; kk++) {
			left[kk] = kk - 1;
			right[kk] = kk + 1;
		}
		left[1] = n;
		right[n] = 1;
		for(int kk=0;kk<q;kk++) {
			int i, j; 
			char s,ch;
			while ((ch = getchar()) != '\n' && ch != EOF) {};
			scanf("%c %d %d",&s, &i, &j);
			if (s == 'A') {
				right[left[i]] = right[i];
				left[right[i]] = left[i];
				right[i] = j;
				left[i] = left[j];
				right[left[i]] = i;
				left[right[i]] = i;
			}
			else if (s == 'B') { 
				right[left[i]] = right[i];
				left[right[i]] = left[i];
				left[i] = j;
				right[i] = right[j]; 
				right[left[i]] = i;
				left[right[i]] = i;
			}
			else if (s=='Q') { 
				if (i == 0) {
					printf("%d\n",left[j]);
				}
				else if(i==1) { 
					printf("%d\n", right[j]);
				}
			}
		}
	}
	return 0;
}

解后反思: 较之于循环链表,静态版本的双向循环链表写起来不很复杂,同时在很多情况下能比较有效地降低时间复杂度。

7-4 幸福指数

原题呈现:
在这里插入图片描述

解题思路: 用纯暴力遍历的话时间复杂度过高,会超出时间限制。因而考虑对每一个数,找出其左边和右边第一个比其小的数(这里可以利用单调栈在线性时间内求出并保存在数组中),由此得出对于每一个数的最大幸福指数。再通过比较得出所有数最大幸福指数的最大值即可。

以下是根据这一思路写出的代码:

#include <iostream>
#include <stack>
using namespace std;
int num[100010];
long long numsum[100010];
stack<int> sl;
stack<int> sr;
int sleft[100010],sright[100010];

int main(void)
{
    int n, i, l = 0, r = 0, tmpl, tmpr;
    long long max = 0, tmpmax;
    cin >> n;
    for (i = 0; i < n; i++) {
        scanf("%d", &num[i]);
        if (i == 0)
            numsum[i] = num[i];
        else if (i != 0)
            numsum[i] = numsum[i - 1] + num[i];
    }
    for (i = 0; i < n; i++) {
        if (sl.empty()) {
            sleft[i] = -1;
            sl.push(i);
            continue;
        }
        while (!sl.empty() && num[sl.top()] >= num[i])
            sl.pop();
        if (!sl.empty())
            sleft[i] = sl.top();
        else
            sleft[i] = -1;
        sl.push(i);
    }
    for (i = n-1; i >= 0; i--) {
        if (sr.empty()) {
            sright[i] = -1;
            sr.push(i);
            continue;
        }
        while (!sr.empty()&&num[sr.top()] >= num[i])
            sr.pop();
        if (!sr.empty())
            sright[i] = sr.top();
        else
            sright[i] = -1;
        sr.push(i);
    }

    for (i = 0; i < n; i++) {
        if (sleft[i] == -1)
            tmpl = 1;
        else
            tmpl = sleft[i] + 1 +1;
        if (sright[i] == -1)
            tmpr = n;
        else
            tmpr = sright[i];
        if(tmpl==1)
            tmpmax = numsum[tmpr-1] * num[i];
        else
            tmpmax = (numsum[tmpr-1]-numsum[tmpl-2]) * num[i];
        if (tmpmax > max) {
            l = tmpl;
            r = tmpr;
            max = tmpmax;
        }
        else if (tmpmax == max && (tmpr - tmpl) > r - l) {
            l = tmpl;
            r = tmpr;
        }
    }
    printf("%lld\n", max);
    printf("%d %d", l, r);

    return 0;
}

解后反思: 博主对单调栈的掌握不够熟练,因而上机时面对实际题目情境根本不能联想到单调栈的知识。

标签:JLU,head,上机,int,next,++,num,数据结构,data
来源: https://blog.csdn.net/sunshy___/article/details/116935317

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有