头歌 JAVA 实验七——线程

前言:

历时十二日,博客再更新,博主深感愧疚,由于近日沉迷于原神,且临近期末,日后更新可能会更慢,直至考试结束。望看官们海涵。

第1关:创建三个线程,并进行同步调

任务描述

本关任务: 创建三个线程Thread1、Thread2及Thread3。三个线程要进行同步调度。

要求:

不管各线程的优先级及各线程sleep的时间,Thread1首先运行,获取数据后将数据存储在数据对象中,Thread2从数据对象中取值加10后存回数据对象,并输出;Thread3从数据对象中取值加10后输出。这三个线程运行必须同步,运行时序如下:

img

实验已经定义了一个类Gatherinfo(如下),该类的GetVal()方法完成数据的生成。

class Gatherinfo{    public int GetVal() {        int n = (int)(Math.random()*20+10);        return n;    }}

线程Thread1类继承类Gatherinfo,在Thread1类中直接调用Gatherinfo类中GetVal()方法获取采集的数据。 类dataObj完成各线程的数据交换。有两个方法: void put(int n);将数据存入数据对象中。 int get();返回数据对象中的数据。 `` Gatherinfo类系统已完成,不需要大家编此类的程序。 每个线程循环运行10次以上,各线程的输出格式如下: 10 20 30 16 26 36 每个数字代表一个线程的输出。 按要求完成Thread1、Thread2、Thread3类的编写。

最后设计一个类来测试你的所有的程序。


开始你的任务吧,祝你成功!

原理:

  • 首先我们得知道什么是线程,在我的理解中,一个程序就是一个进程,我们玩的原神游戏是个进程,自己写的程序也算是一个进程,只是小一点而已。而线程就是进程的一部分,一个进程可能要干很多事,比如原神,我们通过cpu将数据解析是个线程,通过cpu调取内存也是个线程。cpu在任何时候都只能跑一个线程,但由于线程之间的调度,和cpu运行速度非常快,所以在我们看来几个线程是可以同步运行的。

  • 对于这道题,我们需要知道几个线程调度的方法,如wait()和notify()。

    • wait()是停止当前线程。
    • notify()是唤醒当前所有在等待的线程中的优先级最高的且等待时间最久的那个。
  • 这道题还有一个思路就是:各个线程对数据对象的读写操作都是通过调用数据对象的方法来实现,这样对于同一数据对象的线程调度比较方便。

  • 这题还有一个要注意的地方,Thread1由于题目要求要继承一个类,所以它是通过runnable接口实现接口,而Thread2和Thread3只需要继承个Thread类就行了。

源码:

dataObj类

package step1;
//在此写dataObj类
public class dataObj{
    public int vul;
    public int state=1;
    public void put(int n){
        vul=n;
    }
    public int get(){
        return vul;
    }
    public synchronized void func1(int n) {
        if(state!=1) {
            try{
                wait();
            }catch(Exception r) {
                
            }
        }
        vul=n;
        System.out.print(vul+" ");
        state=2;
        notify();
    }
    public synchronized void func2() {
        if(state!=2) {
            try{
                wait();
            }catch(Exception r) {
                
            }
        }
        vul+=10;
        System.out.print(vul+" ");
        state=3;
        notify();
    }
    public synchronized void func3() {
        if(state!=3) {
            try{
                wait();
            }catch(Exception r) {
                
            }
        }
        System.out.print((vul+10)+" ");
        System.out.println();
        state=1;
        notify();
    }
}

Thread1类

package step1;
//在此写Thread1类
public class Thread1 extends Gatherinfo implements Runnable {
    public dataObj d;
    public Thread1(dataObj d) {
        this.d=d;
    }
    @Override
    public void run() {
        // TODO 自动生成的方法存根
        for(int i=0;i<10;i++) {
            int t=GetVal();
            d.func1(t);    
        }
    }
}

Thread2类

package step1;
//在此写Thread2类     
public class Thread2 extends Thread {
    dataObj d;
    public Thread2(dataObj d) {
        this.d=d;
    }
    @Override
    public void run() {
        // TODO 自动生成的方法存根    
        for(int i=0;i<10;i++) {
            d.func2();
        }        
    }
}

Thread3类

package step1;
//在此写Thread3类
public class Thread3 extends Thread  {
    dataObj d;
    public Thread3(dataObj d) {
        this.d=d;
    }
    @Override
    public void run() {
        // TODO 自动生成的方法存根        
        for(int i=0;i<10;i++) {
            d.func3();
        }        
    }
}

头歌 数据结构 实验六——图的存储及操作(合集)

前言:

这些题的提示给的都非常充分了,基本上按照要求来都可以做出来,大家加油 p( ^ O ^ )q 加油!

邻接矩阵

第1关:有向图邻接矩阵的构建

status CreateDG(MGraph &m) //ÓÐÏòͼ´´½¨ 
{
    /********begin********/
    int incinfo,i,j,k;
    VertexType v1,v2;
    cin>>m.vexnum>>m.arcnum>>incinfo;
    for(int i=0;i<m.vexnum;i++){
        cin>>m.vex[i];
    }
    for(i=0;i<m.vexnum;i++){
        for(j=0;i<m.vexnum;i++){
            m.arcs[i][j].adj=0;
            m.arcs[i][j].info=NULL;
        }
    }
    for(k=0;k<m.arcnum;k++){
        cin>>v1>>v2;
        i=LocateVex(m,v1);
        j=LocateVex(m,v2);
        m.arcs[i][j].adj=1;
        if(incinfo){
            cin>>m.arcs[i][j].info;
        }
    }
    /*********end*********/
    return OK;
}

第二关:邻接矩阵存储的有向图的深度优先遍历以及广度优先遍历

void DFS(MGraph &m,int v)
{//µÝ¹éÉîËÑ 
    /*********begin***********/
    stack<int> s;
    s.push(v);
    visited[v]=1;
    cout<<m.vex[v];
    while(!s.empty()){
        int now,flag=0;
        now=s.top();
        for(int i=0;i<m.vexnum;i++){
            if(m.arcs[now][i].adj==1&&!visited[i]){
                s.push(i);
                visited[i]=1;
                cout<<m.vex[i];
                flag=1;
                break;
            }
        }
        if(flag==0){
            s.pop();
        }
    }
    /**********end************/
}
void BFSTraverse(MGraph &m)
{
    for(int i=0;i<m.vexnum;i++) visited[i]=0;
    queue<int> q;
    /************begin*****************/
    int t=0;
    q.push(t);
    visited[t]=1;
    cout<<m.vex[t];
    while(!q.empty()){
        int now;
        now=q.front();
        for(int i=0;i<m.vexnum;i++){
            if(m.arcs[now][i].adj==1&&!visited[i]){
                q.push(i);
                visited[i]=1;
                cout<<m.vex[i];
            }
        }
        q.pop();
    }
    /*************end******************/
}

第3关:邻接矩阵存储的有向图的拓扑排序

status TopologicalSort(MGraph &m)
{
    int InDegree[m.vexnum]={0};
    int i,count,ans,temp,j;
    stack<int> s;
    for(i=0;i<m.vexnum;i++)
    {
        count=0;
        for(j=0;j<m.vexnum;j++)
        {
            if(m.arcs[i][j].adj) InDegree[j]++;
        }
    }
    /***********begin**********/
    for(int i=0;i<m.vexnum;i++){
        if(InDegree[i]==0){
            s.push(i);
        }
    }
    while(!s.empty()){
        int now=s.top();
        s.pop();
        cout<<m.vex[now];
        for(int i=0;i<m.vexnum;i++){
            if(m.arcs[now][i].adj==1){
                InDegree[i]--;
                if(InDegree[i]==0){
                    s.push(i);
                }
            }
        }
    }
    /***********end************/ 
}

邻接表

第1关:实现图的邻接表存储

tips:

这题老师给的print函数有问题,你们需要自己改,如果不改输出的格式肯定就不对,需要把空格放在数字的前面

void Creat_ALG(ALGraph *m){
    VertexType a,b;//Æðµãa£¬ÖÕµãb 
    for(int i=0;i<m->arcnum;i++){
        //printf("ÇëÊäÈëÆðµãºÍÖյ㣺\n");
        scanf("%d%d",&a,&b);
        /************begin************/ 
        int x,y;
        for(int j=0;j<m->vexnum;j++){
            if(a==m->vertices[j].data){
                x=j;
            }
            if(b==m->vertices[j].data){
                y=j;
            }
        }
        ArcNode *p=new ArcNode;
        p->num=y;
        ArcNode *t=m->vertices[x].firstarc;
        if(!t){
            p->next=t;
            m->vertices[x].firstarc=p;
        }else{
            while(t->next!=NULL){
                t=t->next;
            }
            p->next=t->next;
            t->next=p;
        }
        /************end************/ 
    } 
}

第2关:基于邻接表存储实现图的两种遍历算法

tips:

这题老师给的print函数同样有问题,你们需要自己改

void dfs(stack<int> &s,ALGraph m,int visit[]){//Ó÷ûºÅ&ʵÏÖË«Ïò´«µÝ 
    //Éî¶ÈÓÅÏȱéÀú 
    /*************begin*************/
    while(!s.empty()){
        int now,temp=0;
        now=s.top();
        ArcNode *p=m.vertices[now].firstarc;
        while(p!=NULL){
            if(visit[p->num]==0){
                s.push(p->num);
                visit[p->num]=1;
                cout<<" "<<m.vertices[p->num].data;
                temp=1;
                break;
            }
            p=p->next;
        }
        if(temp==0){
            s.pop();
        }
    } 
    /*************end*************/
}
void bfs(queue<int> &q,ALGraph m,int visit[]){
    //¹ã¶ÈÓÅÏȱéÀú
    /*************begin*************/
    while(!q.empty()){
        int now,temp;
        now=q.front();
        ArcNode *p=m.vertices[now].firstarc;
        while(p!=NULL){
            if(visit[p->num]==0){
                q.push(p->num);
                visit[p->num]=1;
                cout<<" "<<m.vertices[p->num].data;
            }
            p=p->next;
        }
        q.pop();
    }
    /*************end*************/
}

第3关:实现DAG图的拓扑排序

void FindInDegree(ALGraph G,int a[]){//ͳ¼Æ¸÷¸ö¶¥µãµÄÈë¶È 

    /*************begin*************/
    for(int i=0;i<G.vexnum;i++){
        ArcNode *p=G.vertices[i].firstarc;
        while(p!=NULL){
            a[p->num]++;
            p=p->next;
        }
    }
    /*************end*************/
}
void TopologicalSort(ALGraph G){//ÍØÆËÅÅÐòº¯Êý
 
    int indegree[G.vexnum+1];//indegreeÊý×éÀ´¼Ç¼¶¥µãµÄÈë¶È 
    
    memset(indegree,0,sizeof(indegree));//Êý×éÔªËسõʼ»¯Îª0 
    
    FindInDegree(G,indegree);//µ÷ÓÃͳ¼ÆÈë¶Èº¯Êý 
    
    /*************begin*************/
    stack<int> s;
    for(int i=0;i<G.vexnum;i++){
        if(indegree[i]==0){
            s.push(i);
        }
    }
    while(!s.empty()){
        int now=s.top();
        s.pop();
        cout<<G.vertices[now].data<<" ";
        ArcNode *p=G.vertices[now].firstarc;
        while(p!=NULL){
            indegree[p->num]--;
            if(indegree[p->num]==0){
                s.push(p->num);
            }
            p=p->next;
        }
    }
    /*************end*************/
}

头歌 JAVA 实验六——输入输出

前言:

多日没更,深感愧疚,今日闲来无事,习得实验六,在此与诸君分享,望诸君支持。

第一关:从文件读取一篇英语文章,然后统计26个英文字母出现的次数

任务描述

本关任务:从文件读取一篇英语文章,然后统计26个英文字母出现的次数。

要求:

  1. 按26个字母的顺序统计出每个字母出现的次数。

  2. 用于统计次数的类FileLetter,只有一个方法: public int[] LetterStatistics(String strFilename); strFilename是输入的需统计的文件名; 返回的是一个整型数组,大小26,每个位置存放的分别是a到z出现的次数。

    大小写字母算同一个字母。


开始你的任务吧,祝你成功!

解法:

无它,手熟尔!

源码:

package step1;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;

//在此写FileLetter类
public class FileLetter {
    
    private FileInputStream read;
    
    public int[] LetterStatistics(String strFilename){
        try{
            read=new FileInputStream(strFilename);
            int[] letter=new int[26];
            int b=read.read();
            char a='a';char A='A';
            while(b!=-1) {
                if(b-(int)a>=0&&b-(int)a<26) {
                    letter[b-(int)a]++;
                }
                else if(b-(int)A>=0&&b-(int)A<26) {
                    letter[b-(int)A]++;
                }
                b=read.read();
            }
            read.close();
            return letter;
        }catch(IOException ioe) {
            ioe.printStackTrace();
            return null;
        }    
    }
}

第2关:文件的随机访问

任务描述

本关任务:创建一个学生类Student,包括姓名name,年龄age两个属性。姓名的长度不超过10个字符,年龄是int类型。使用随机读写类RandomAccessFile将学生信息写入到文件中,并能对文件中的学生信息进行读取和修改。(参照教科书P196,例6-18)。

要求:

学生类的类名为:Student,该类中有两个属性,访问类型都为public: char name[]=new char[10]; //学生姓名 int age;//年龄 public Student(String name,int age)构造函数 public void Print();显示姓名和年龄 ``
还须创建一个读写类RWClass,该类有一个属性filename,打开读写的文件名。 public RWClass(String filename) 该类的构造函数 public void saveStudent(Student ss,int pos) 将学生对象的信息保存在文件中,ss为保存的学生信息,pos保存的位置。 public Student readStudent(int pos) 在文件中读出某位置的一个学生的信息,返回学生对象


开始你的任务吧,祝你成功!

解法:

书中有例,可效仿之。

源码:

Student.class
package step2;
//在此写Student类
public class Student {
    char name[]= {'\u0000','\u0000','\u0000','\u0000','\u0000','\u0000','\u0000','\u0000','\u0000','\u0000'};
    int age;
    public Student(String name,int age) throws Exception {
        if(name.toCharArray().length>10) {
            System.arraycopy(name.toCharArray(), 0, this.name, 0, 10);
        }else {
            System.arraycopy(name.toCharArray(), 0, this.name, 0, name.toCharArray().length);
        }
        this.age=age;
    }
    public void print() {
        System.out.println("name:"+name.toString());
        System.out.println("age:"+age);
    }
}
RWClass.class
package step2;
import java.io.*;
//在此写RWClass类
public class RWClass {

    String filename;
    public RWClass(String Filename) {
        filename=Filename;
    }
    public void saveStudent(Student ss,int pos) throws Exception{
        RandomAccessFile ra=new RandomAccessFile(filename,"rw");
        ra.seek(pos*24);
        for(int i=0;i<10;i++) {
            ra.writeChar(ss.name[pos]);
        }
        ra.writeInt(ss.age);
        ra.close();
    }
    public Student readStudent(int pos) throws Exception{
        char buf[]=new char[10];
        RandomAccessFile ra=new RandomAccessFile(filename,"r");
        ra.seek(pos*24);
        for(int i=0;i<10;i++) {
            buf[i]=ra.readChar();
        }
        Student ss=new Student(buf.toString(),ra.readInt());
        ra.close();
        return ss;
    }
}

最短路径——迪杰斯特拉(Dijkstra)算法

前言:

马上新一轮的ACM考核就要来了,而这一次的考核内容包括了弗洛伊德算法,而由于弗洛伊德算法是由迪杰斯特拉算法改进而得到的,所以准备先复习这个算法,然后随便找道题写一下。

旅游规划

有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

输入格式:

输入说明:输入数据的第1行给出4个正整数NMSD,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。

输出格式:

在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

输入样例:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
结尾无空行

输出样例:

3 40
结尾无空行

原理:

  • 首先,选定一个点v 0 v0v0,先假设所有的点到某个点的路径都是无穷(当然自己到自己肯定得是长度是0…)。
  • 然后确定一个集合S SS,这集合表示已经被访问的过点。(那么没有被访问过的点,也是很容易解决的…),这里用个bool数组什么的标记一下吧。
  • 之后,先更新所有点到这个v 0 v0v0的距离。怎么更新呢?
  • 所有点通过已经被访问过的点到达v 0 v0v0的距离,在结合d ( v 0 , v i ) = m i n v j ∈ ( S ) ( d ( v 0 , v j ) + w ( v j , v i ) ) d(v0, vi) = min_{vj \in (S)}(d(v0, vj) + w(vj, vi))d(v0,vi)=min vj∈(S)(d(v0,vj)+w(vj,vi)) ( 一般就是新增加的那个点考虑下就好了 )。就是在中间搭一个桥,如果,通过这个桥的点会让这个路变得更近,就更新这个路径的长度。
  • 然后选个最近的点,然后把这个最近的点标记访问过。纳入到集合S SS
  • 然后,一直到把所有的点都纳入进去之后,就没什么事情了~

是不是感觉直接看不懂?小问题,我将通过借助此题来解释其原理。
首先我们画出这个旅游图:

image-20211130111303127

这里我们需要注意这是高速公路,是双向的。
这个算法的目的是算出一个节点到其他所有节点的最短路径,所以我们首先就需要一个大小为节点数的一维数组来存储最短路径的值。如Path[4]={0,1,2,4},这里我们先存储能直接到达的,不能到达就用正无穷表示,而出发地自然用0表示。然后我们还需要一个bool数组来存储是否算出了最短路径。初始化后的arrived[4]={true,false,false,false},然后我们找出没达到过的里面的最短的路径,明显是节点1,并将其置为已到达过即为arrived[4]={true,true,false,false},然后遍历节点1所能到达的所有节点,并把权重相加后与原始Path里的最短路径相比较,然后比它小,就更新它,第一次比较后:**Path[4]={0,1,2,3}**,直到所有节点都访问过,这样我们就得到了所有的最短路径。

源码:

#include<iostream>
#include<cstring>
const int N=500;
const int INf=999999;//代表正无穷
int map[N][N][2];//同时存储路径长度和费用
using namespace std;
int answer[2];//结果
int n;
void minpath(int s,int e){
    int dis[n][2],t=INf,flag;
    bool arrived[n];
    memset(arrived,false,sizeof(arrived));
    memset(dis,INf,sizeof(dis));
    arrived[s]=true;
    //初始化最短路径
    for(int i=0;i<n;i++){
        dis[i][0]=map[s][i][0];
        dis[i][1]=map[s][i][1];
    }
    dis[s][0]=0;dis[s][1]=0;
    for(int i=0;i<n;i++){
        flag=0;t=INf;
        for(int j=0;j<n;j++){
            if(!arrived[j]&&dis[j][0]<t){
                t=dis[j][0];
                flag=j;
            }
        }
        arrived[flag]=true;
        for(int j=0;j<n;j++){
            if(!arrived[j]&&dis[flag][0]+map[flag][j][0]<dis[j][0]){
                dis[j][0]=dis[flag][0]+map[flag][j][0];
                dis[j][1]=dis[flag][1]+map[flag][j][1];
            }else if(!arrived[j]&&dis[flag][0]+map[flag][j][0]==dis[j][0]&&dis[flag][1]+map[flag][j][1]<dis[j][1]){//取费用最小的
                dis[j][1]=dis[flag][1]+map[flag][j][1];
            }
        }
    }
    //得出结果
    answer[0]=dis[e][0];
    answer[1]=dis[e][1];
}
int main(){
    int m,start,end,s,d,v,p;
    cin>>n>>m>>start>>end;
    //初始化地图
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(i==j){
                map[i][j][0]=0;
                map[i][j][1]=0;
            }else{
                map[i][j][0]=INf;
                map[i][j][1]=INf;
            }
        }
    }
    //录入地图
    for(int i=0;i<m;i++){
        cin>>s>>d>>v>>p;
        map[s][d][0]=v;
        map[s][d][1]=p;
        map[d][s][0]=v;
        map[d][s][1]=p;
    }
    minpath(start,end);
    cout<<answer[0]<<" "<<answer[1];
    return 0;
}

头歌 数据结构 实验七——数据查找与排序

前言:

这次一下更新两个实验,都是很简单的东西,就一些简单的排序和查找,也就不解释啦。

查找

第1关:查找特定的数据元素-顺序查找

#include <stdio.h>

int find_pos(int data[] ,int n, int key)
{//在数组data中查找给定数据key,n表示数组中数据元素的个数
 /*------------begin-----------------*/
  for(int i=0;i<n;i++){
    if(data[i]==key){
      return i;
    }
  }
  return -1;
 /*------------end-----------------*/
}

int main(void)
{
int a[]={99,23,5,189,-1,66};
int x;
scanf("%d",&x);
//此处填写代码,调用find_pos,在a数组中查找给定数据x的位置,并输出函数返回的数据元素的位置
  /*------------begin-----------------*/
  int p=find_pos(a,6,x);
  printf("%d",p);
 /*------------end-----------------*/   
    
return 1;
}

第2关:查找-进阶(二分查找)

#include <stdio.h>

int find_pos(int data[] ,int n, int key)
{//在数组data中查找给定数据key,n是数组中数据元素的个数,返回值是数据元素比较的次数.
    
 /*------------begin-----------------*/
  int low=0,high=n-1,count=0;
  if(key<data[0]||key>data[n-1]){
    return count;
  }
  while(low<=high){
    int mid=(low+high)/2;
    if(key==data[mid]){
      count++;
      return count;
    }
    if(key<data[mid]){
      high=mid-1;
      count++;
    }else if(key>data[mid]){
      low=mid+1;
      count++;
    }
  }
  return count;
 /*------------end-----------------*/
}

int main(void)
{
int a[]={-1,15,66,99,122,189};
int x;
scanf("%d",&x);
//此处填写代码,调用find_pos,在a数组中查找给定数据x的位置,并输出函数返回值
  /*------------begin-----------------*/
  int p=find_pos(a,6,x);
  printf("%d",p);
 /*------------end-----------------*/   
    
return 1;
}

第3关:查找进阶

#include <stdio.h>
void compute(int data[],int n, int target)
{//在此处填写代码,在data数组中查找是否存在两个元素之和为target,并按要求输出
  /*-----------begin---------------*/ 
  int a=-1,b=-1;
  for(int i=0;i<n-1;i++){
    for(int j=i+1;j<n;j++){
      if(data[i]+data[j]==target){
        a=i;b=j;
      }
    }
  }
  printf("%d,%d",a,b);
 /*-----------end---------------*/ 

}

int main(void)
{
    int a[]={-3,2,5,9,15,32};
    int x ;
    scanf("%d",&x);
    compute(a,6,x);
}

排序

第1关:冒泡排序

#include <stdio.h>
void print(int a[] ,int n)
{//输出数组元素,数字之间以一个空格为界,输出结束后换一行
  for(int i=0;i<n;i++){
    printf("%d ",a[i]);
  }
  printf("\n");
}

void bubbleSort(int a[] ,int n) //对数组a中的n个元素进行排序,调用print函数输出每趟排序后的结果
{
  int m=n,flag=1,t=0;
  while(flag==1&&m>1){
    flag=0;
    t++;
    for(int i=0;i<m-1;i++){
      if(a[i]>a[i+1]){
        flag=1;
        int tmp=a[i];
        a[i]=a[i+1];
        a[i+1]=tmp;
      }
    }
    if(flag==1||t==1){
      print(a,n);
    }
    m--;
  }



}


int main(void)
{
  int num ;
  scanf("%d",&num);
  int data[num];
  for(int i=0;i<num;i++)
    scanf("%d",&data[i]);

  bubbleSort(data ,num);
}

第2关:快速排序

#include <stdio.h>
void print(int a[] ,int n)
{//输出数组元素,数字之间以一个空格为界,输出结束后换一行
  for(int i=0;i<n;i++){
    printf("%d ",a[i]);
  }
  printf("\n");
}
void qSort(int a[] ,int left, int right) //
{
  int flag=0,tleft=left,tright=right;
  if(tleft<tright){
    int tmp=a[tleft];
    while(tleft<tright){
      while(tleft<tright&&a[tright]>=tmp){
        tright--;
      }
      a[tleft]=a[tright];
      while(tleft<tright&&a[tleft]<=tmp){
        tleft++;
      }
      a[tright]=a[tleft];
    }
    a[tleft]=tmp;
    flag=tleft;
    print(a,right+1);
    qSort(a,left,flag-1);
    qSort(a,flag+1,right);
  }
}
int main(void)
{
  int num ;
  scanf("%d",&num);
  int data[num];
  for(int i=0;i<num;i++)
    scanf("%d",&data[i]);

  qSort(data ,0,num-1);
  print(data,num);
}

头歌 Java 实验五——集合框架

前言:

今天晚上心血来潮,准备写道Java的题,打开头歌找到了这个,原以为会很快解决这题,但没想到的是我还是花了一个多小时,主要还是不够理解HashMap这个类。主要就是要注意到HashMap的key和value都得是类,比如int的包裹类是Integer

第1关: 实验五

任务描述

本关任务:设计一个程序,管理一个班级的若干学生(学生的姓名是唯一的),每个学生都修了若干门课程,没门课程都有了一个成绩。但一个班的同学修的课程不完全一样。

要求:

该程序用集合框架的Map接口来实现。学生用Map来存储,键用学生姓名,值是另一个存储课程的Map;每个同学修的若干门课程也用Map来存储,键是课程名称,值是该课程的成绩。

  • 将把完成的工作放在Class类中。 类名:Class public Class(String name) 构造函数,name为班级名称;
  • public void addCourseGrade(String stuname,String []Coursenames,Integer[] grades) 增加学生及课程的数据,stuname 学生姓名,Coursenames多个课程名,grades对应的多个分数;
  • public void addCourseGrade(String stuname,String Coursename,Integer grade) 增加学生及课程的数据,stuname 学生姓名,Coursename课程名,grade对应的分数;
  • public void delStudent(String stuname) 删出一个学生,stuname学生姓名;
  • public void delStuCourse(String stuname,String Coursename) 删出一个学生的一门课程,stuname学生姓名,Coursename课程名;
  • public double getPerAvgStudent(String stuname)返回一个学生的所有课程的平均成绩,stuname学生姓名; ``
  • public double getClassAvgCourse(String Coursename) 返回一个班某门课程的平均成绩,如果该班有同学没选修该门课程,平均成绩不计算该同学,Coursename为课程名。

开始你的任务吧,祝你成功!

提示:

  1. 构造函数中的字符串是没用的,写代码时不需要过多纠结name是干啥的,只要加上就行了。
  2. 学生的HashMap需要封装成类(内部类)。
  3. 添加课程时不能把原有课程给覆盖了。

源码:

package step1;
import java.util.*;
//在此写Class类
public class Class {
    
    class Student{
        public  HashMap<String,Integer> courses=new HashMap<String, Integer>();//存储课程
    }
    
    private HashMap<String,Student> students; //存储学生
    
    
    public  Class(String name) {
        students=new HashMap<String,Student>();//不用关心name干啥
    }
    //添加多个课程
    public void addCourseGrade(String stuname,String []Coursenames,Integer[] grades) {
        Student a=null;
        for(String s:students.keySet()) {
            if(s.equals(stuname)) {
                a=students.get(stuname);
            }
        }
        if(a==null) {
            a=new Student();
        }
        for(int i=0;i<Coursenames.length;i++) {
            a.courses.put(Coursenames[i], grades[i]);
        }
        students.put(stuname, a);
    }
    //添加单个课程
    public void addCourseGrade(String stuname,String Coursename,Integer grade) {
        Student a=null;
        for(String s:students.keySet()) {
            if(s.equals(stuname)) {
                a=students.get(stuname);
            }
        }
        if(a==null) {
            a=new Student();
        }
        a.courses.put(Coursename, grade);
        students.put(stuname, a);
    }
    //删除学生
    public void delStudent(String stuname) {
        students.remove(stuname);
    }
    //删除课程
    public void delStuCourse(String stuname,String Coursename) {
        students.get(stuname).courses.remove(Coursename);
    }
    //得到学生的平均分
    public double getPerAvgStudent(String stuname) {
        double goal=0;
        for(Integer i:students.get(stuname).courses.values()) {
            goal+=i;
        }
        return goal/students.get(stuname).courses.size();
    }
    //得到课程的平均分
    public double getClassAvgCourse(String Coursename) {
        double goal=0;
        int number=0;
        for(Student s:students.values()) {
            for(String a:s.courses.keySet()) {
                if(a.equals(Coursename)) {
                    goal+=s.courses.get(Coursename);
                    number++;
                }
            }
        }
        return goal/number;
    }
}
  • Copyrights © 2021-2022 舒窈
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信