数据结构实验(一)程序设计回顾

1|06-1 最大子段和


因为是字段和,所以要尽可能的多加,如果在加的过程中当前和为负数时,往后累加一定不会比保留当前值更优秀,所以要把之前的部分抛弃重新累加

int mis(int a[], const int n) { int res = 0 , sum = 0 ; for( int i = 0 ; i < n ; i ++ ){ sum += a[i]; if( sum > res ) res = sum; if( sum < 0 ) sum = 0; } return res; }

2|06-2 日期类型


判断闰年的标准操作

int IsLeapYear(int year){ if( year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ) return 1; return 0; }

3|06-3 调整数组使奇数全部都位于偶数前面其他数字顺序不变


这题有个很奇怪的地方就是数据中是没有的多余的换行符的,但是输出却是用putsputs会默认输出一个换行符。所以我exit函数提前结束了程序,没有使用主程序给的输出函数

void fun ( char s[] ){ for( int i = 0 ; i < strlen(s) ; i ++ ) if( (s[i] - '0') % 2 == 1 ) printf("%c" , s[i] ); for( int i = 0 ; i < strlen(s) ; i ++ ) if( (s[i] - '0') % 2 == 0 ) printf("%c" , s[i] ); exit(0); }

4|07-1 链表操作


这里的链表操作是非常基础的

首先输出是反复被调用的,所以可以先写输出链表的函数,这里输出的时候可以使用结构化绑定非常好用

void print(){ for( auto [ id , name , age ] : l ) cout << id << " " << name << " " << age << "\n"; }

要注意的是,最初建立链表是逆向链表,这里我用了双向链表,每次都在头部插入。

删除第 m 个节点其实也比较简单,就是从第一个节点向后跳 m 次删除就好了。

删除指定的学号就要把整个序列一遍就好了。

#include<bits/stdc++.h> using namespace std; int read() { int x = 0, f = 1, ch = getchar(); while ((ch < '0' || ch > '9') && ch != '-') ch = getchar(); if (ch == '-') f = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } typedef tuple<int,string,int> stu; list<stu> l; void print(){ for( auto [ id , name , age ] : l ) cout << id << " " << name << " " << age << "\n"; } void getStu( stu & it ){ auto & [ id , name , age ] = it; id = read() , cin >> name , age = read(); } void solve(){ int n = read(); l.clear(); for( stu it ; n ; n -- ){ getStu(it); l.push_front( it ); } print(); { int m = read(); stu cur ; getStu(cur); auto it = l.begin(); while( m ) it ++ , m --; l.insert( it , cur ); } print(); { int id = read(); for( list<stu>::iterator it = l.begin() ; it != l.end() ; it ++ ) if( get<0>(*it) == id ) it = l.erase(it) -- ; } print(); } int32_t main() { for( int T = read() ; T ; T -- ) solve() , cout << ( T == 1 ? "" : "\n"); return 0; }

5|07-2 单链表基本操作


这个题其实相比上一题更加简单了,我就手写一下链表,还是很轻松的

不过这道题还是让我发现了一个值得考虑的问题,来看一下我最初写的链表的构造函数

List(){ size = 0; begin = end = nullptr; }

看似是没有问题,那么在看一下我的插入函数吧

void insert( int pos , int val ){ if( pos > size ) return; auto it = begin; while( pos ) pos -- , it = it->next ; it->next = new Node( val , it->next ); size ++; }

这个时候,我在插入第一个元素的时候就会直接执行it->next = new Node( val , it->next)但是此时我的 it 就是begin ,而begin还是指向nullptr的就会直接导致RE,所以因为这里是单链表,正确的解决方法是

List(){ size = 0; end = nullptr; begin = new Node( 0 , end ); }

begin指向一个空节点就好了。那么此时要注意的就是实际上链表的第一个节点应该是begin->next

虽然这个问题有其他的解决方法,要注意的是这里道题问题是可能会在0的位置插入节点,所以其他的方法还有特判begin==nullptr或者是直接写双向链表。

#include<iostream> struct Node{ int val ; Node * next; Node( int val , Node * next ) : val(val) , next(next){}; }; class List{ private: int size; Node * begin , * end; public: List() { size = 0; end = nullptr; begin = new Node( 0 , end ); } void insert( int pos , int val ){ if( pos > size ) return; auto it = begin; while( pos ) pos -- , it = it->next ; it->next = new Node( val , it->next ); size ++; } void print(){ for( auto it = begin->next ; it != end ; it = it->next ) std::cout << it->val << " "; std::cout << "\n"; } void remove( int pos ){ if( pos > size || pos == 0 ) return; auto it = begin; while( pos > 1 ) pos -- , it = it->next; it->next = it->next->next; size --; } }; int read() { int x = 0, f = 1, ch = getchar(); while ((ch < '0' || ch > '9') && ch != '-') ch = getchar(); if (ch == '-') f = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } int main(){ List list; int n = read(); for( int v , i = 0 ; i < n ; i ++ ) v = read() , list.insert( i , v ); for( int m = read() , op , k , v ; m ; m -- ){ op = read(); if( op ){ k = read(); list.remove(k); } else{ k = read() , v = read(); list.insert( k , v ); } } list.print(); return 0; }

6|07-3 报销


这题其实非常简单的,定义一个结构体,然后重载一下运算符就好了

#include<bits/stdc++.h> using namespace std; struct account{ int id , val; string name; account( int id , int val , string name ) : val(val) , name(name) , id(id){}; friend bool operator < ( account a , account b ){ if( a.val != b.val ) return a.val > b.val; if( a.name != b.name ) return a.name < b.name; return a.id < b.id; } }; void solve(){ int n , m; cin >> n >> m; vector< account > ve; vector<int> rank; for( auto [ id , name , val ] = tuple{ 1 , (string)"" , 0 } ; id <= n ; id ++ , val = 0 ){ cin >> name; for( int x , i = 1 ; i <= m ; i ++ ) cin >> x , val += x; ve.push_back( account( id , val , name ) ); rank.push_back(val); } sort( ve.begin() , ve.end() ) , sort( rank.begin() , rank.end() , greater<int>() ); for( auto [id , val , name] : ve ){ int rk = lower_bound( rank.begin() , rank.end() , val ,greater<int>() ) - rank.begin() + 1 ; cout << rk << " " << id << " " << name << " " << val << "\n"; } } int main(){ int T ; cin >> T; for( int i = 1 ; i <= T ; i ++ ) cout << "Case " << i << ":\n" ,solve() , cout << ( i != T ? "\n" : "" ); }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/16647045.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(184)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示