C#进程调度的模拟实现:模拟先来先服务调度算法、短作业优先调度算法和优先级调度算法(考虑非抢占式和抢占式),进行算法评价,输出调度结果和算法评价指标。

没什么水平,希望能帮到你

环境:visual studio 2019

附带工程资源:C#进程调度的模拟实现附带资源-C#文档类资源-CSDN下载

先来先服务的调度算法:是一种非抢占式的算法,先来先服务(FCFS: first come first service)总是把当前处于就绪队列之首的那个进程调度到运行状态。也就说,它只考虑进程进入就绪队列的先后,而不考虑它的下一个CPU周期的长短及其他因素。FCFS算法简单易行,是一种非抢占式策略,但性能不大好。

短作业优先调度算法思想:短作业优先调度算法(Short Job First)用于进程调度时又被称为短进程优先调度算法(ShortProcess First),该算法既可以用于作业调度,又可以用于进程调度。在作业调度中,该算法每次从后备作业队列中挑选估计服务时间最短的一个或几个作业,将他们调入内存,分配必要的资源,创建进程并放入就绪队列。在进程调度中的原理类似。SJF是非抢占式的,优先照顾短作业,具有很好的性能,降低平均等待时间,提高吞吐量。但是不利于长作业,长作业可能一直处于等待状态,出现饥饿现象;完全未考虑作业的优先紧迫程度,不能用于实时系统。

优先级调度算法:常用于批处理系统中,在进程调度中,每次调度时,系统把处理机分配给就绪队列中优先数最高的进程,算法又细分为两种:非抢占式优先级算法和抢占式优先级算法。

(1)在非抢占式优先数算法下,系统一旦把处理机分配给就绪队列中优先数最高的进程后,这个进程就会一直运行,直到完成或发生某事件使它放弃处理机,这时系统才能重新将处理机分配给就绪队列中的另一个优先数最高的进程。

(2)在抢占式优先数算法下,系统先将处理机分配给就绪队列中优先数最高的进程度让它运行,但在运行的过程中,如果出现另一个优先数比它高的进程,它就要立即停止,并将处理机分配给新的高优先数进程。

程序大致区分为四部分设计

第一部分:Common区

这里面的类都是整个程序设计的“工具”,一共有三个类存在于此区,分别是PCB定义类,Process定义类和Singleton单例模板工具类。

第二部分:Managers区

这里面的类是为了实现对所有算法的管理而存在的。

第三部分:Algorithms区

这里面的类都是算法的具体实现类,通过与Manager区的管理类相联系实现算法的管理,一共有三个类,分别是FCFS算法定义类,SJF算法定义类和PF算法定义类。

第四部分:Program区

这里面的类是程序的入口类,要完成对算法管理器的初始化和调用。

Common区:

PCB类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace simulation.Common
{
    class PCB
    {
        public string id;  //  进程ID

        public float reachTime;  //  到达时间

        public float needTime;  //  还需时间

        public float startTime;  //  开始时间

        public float finishTime;  //  完成时间

        public Status state;  //  状态

        public float restTime;  //  剩余时间

        public int priority;

        public enum Status
        {
            Ready = 0,
            Runing = 1,
            Block = 2,
            Destory = 3
        }
    }
}

Process类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace simulation.Common
{
    class Process
    {
        public string process_id;

        public PCB processPCB;

        public Process(PCB processPCB)
        {
            this.processPCB = processPCB;
            this.process_id = processPCB.id;
        }


    }
}

SingleTon类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace simulation.Common
{
    public class Singleton<T> where T : new()
    {
        private static T instance;

        public static T Instance
        {
            get
            {
                return Equals(instance, default(T)) ? (instance = new T()) : instance;
            }
        }
    }
}

Managers区:

ProcessManager类

using simulation.Algorithms;
using simulation.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace simulation.Managers
{
    class ProcessManager : Singleton<ProcessManager>
    {
        public Dictionary<string, PCB> processDictionary = new Dictionary<string, PCB>();  //  进程id和PCB字典
        public List<Process> processes = new List<Process>();  //  所有输入的进程

        public bool PFPreemptive = false;

        public float nowTime;

        public void StartFCFS()
        {
            FCFS.Instance.Init();
            FCFS.Instance.Start();

            PrintOut();
            Console.WriteLine("FCFS Finish");
            Reset();
        }

        public void StartSJF()
        {
            SJF.Instance.Init();
            SJF.Instance.Start();

            PrintOut();
            Console.WriteLine("SJF Finish");
            Reset();
        }

        public void StartPF()
        {
            PF.Instance.Init();
            PF.Instance.Start();

            PrintOut();
            Console.WriteLine("PF Finish");
            Reset();
        }


        public void Reset()
        {
            this.processDictionary.Clear();
            this.processes.Clear();
            this.PFPreemptive = false;
            this.nowTime = 0;
        }

        public void PrintOut()
        {
            //float sum1 = 0.0f, sum2 = 0.0f;
            Console.WriteLine("\n进程  到达时间  运行时间  开始时间  完成时间  周转时间  带权周转时间");
            for (int i = 0;i< processes.Count; i++)
            {
                Console.WriteLine("{0,-4} {1,9:F2} {2,9:F2} {3,9:F2} {4,9:F2} {5,9:F2} {6,9:F2}",
                    processes[i].processPCB.id, processes[i].processPCB.reachTime, processes[i].processPCB.needTime,
                    processes[i].processPCB.startTime, processes[i].processPCB.finishTime, processes[i].processPCB.finishTime - processes[i].processPCB.reachTime,
                    (processes[i].processPCB.finishTime - processes[i].processPCB.reachTime)/ processes[i].processPCB.needTime);
            }
        }


    }
}

Algorithms区:

FCFS类 先来先服务

using simulation.Common;
using simulation.Managers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace simulation.Algorithms
{
    class FCFS : Singleton<FCFS>
    {

        Comparison<Process> FCFSComparison = FCFSCompare;

        private static int FCFSCompare(Process x, Process y)
        {

            return x.processPCB.reachTime.CompareTo(y.processPCB.reachTime);

        }

        public void Init()
        {
            string[] nums;

            Console.WriteLine("进程数:");
            string input = Console.ReadLine();
            Console.WriteLine("收到进程数:{0}",input);
            Console.WriteLine("各进程id、到达时间、运行时间");
            for(int i = 0; i < int.Parse(input); i++)
            {
                string t = Console.ReadLine();
                nums = t.Split(new string(" "), StringSplitOptions.None);

                PCB pCB = new PCB();
                pCB.id = nums[0];
                pCB.reachTime = float.Parse(nums[1]);
                pCB.needTime = float.Parse(nums[2]);

                ProcessManager.Instance.processDictionary.Add(pCB.id, pCB);
                ProcessManager.Instance.processes.Add(new Process(pCB));
            }
        }

        public void Start()
        {
            ProcessManager.Instance.processes.Sort(FCFSComparison);

            List<Process> proc = ProcessManager.Instance.processes;

            ProcessManager.Instance.nowTime = proc[0].processPCB.reachTime;

            for (int i =0; i< ProcessManager.Instance.processes.Count;i++)
            {
                if(proc[i].processPCB.reachTime < ProcessManager.Instance.nowTime)
                {
                    proc[i].processPCB.startTime = ProcessManager.Instance.nowTime;
                }
                else
                {
                    proc[i].processPCB.startTime = proc[i].processPCB.reachTime;
                }

                proc[i].processPCB.finishTime = proc[i].processPCB.startTime + proc[i].processPCB.needTime;
                ProcessManager.Instance.nowTime = proc[i].processPCB.finishTime;
            }
        }
    }
}

SJF类 短作业优先调度

using simulation.Common;
using simulation.Managers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace simulation.Algorithms
{
    class SJF : Singleton<SJF>
    {

        Comparison<Process> SJFReachTimeComparison = SJFReachTimeCompare;
        Comparison<Process> SJFNeedTimeComparison = SJFNeedTimeCompare;

        private static int SJFNeedTimeCompare(Process x, Process y)
        {
            return x.processPCB.needTime.CompareTo(y.processPCB.needTime);
        }

        List<Process> SJFPreprocesses = new List<Process>();
        List<Process> SJFAftprocesses = new List<Process>();

        private static int SJFReachTimeCompare(Process x, Process y)
        {
            return x.processPCB.reachTime.CompareTo(y.processPCB.reachTime);
        }

        public void Init()
        {
            string[] nums;

            Console.WriteLine("进程数:");
            string input = Console.ReadLine();
            Console.WriteLine("收到进程数:{0}", input);
            Console.WriteLine("各进程id、到达时间、运行时间");
            for (int i = 0; i < int.Parse(input); i++)
            {
                string t = Console.ReadLine();
                nums = t.Split(new string(" "), StringSplitOptions.None);

                PCB pCB = new PCB();
                pCB.id = nums[0];
                pCB.reachTime = float.Parse(nums[1]);
                pCB.needTime = float.Parse(nums[2]);

                ProcessManager.Instance.processDictionary.Add(pCB.id, pCB);
                ProcessManager.Instance.processes.Add(new Process(pCB));
            }
        }

        public void Start()
        {

            ProcessManager.Instance.processes.Sort(SJFReachTimeComparison);

            List<Process> proc = ProcessManager.Instance.processes;

            ProcessManager.Instance.nowTime = 0;

            for(int j =0;j< proc.Count; j++)
            {
                for (int i = 0; i < proc.Count; i++)
                {
                    if (proc[i].processPCB.reachTime <= ProcessManager.Instance.nowTime && proc[i].processPCB.finishTime == 0)
                    {
                        SJFPreprocesses.Add(proc[i]);  //  当前时间之前到达的且还未执行的进程放到pre列表里
                    }
                    else if (proc[i].processPCB.reachTime > ProcessManager.Instance.nowTime)
                    {
                        SJFAftprocesses.Add(proc[i]);  //  在当前时间之后到达的进程放在aft列表里
                    }
                }
                SJFPreprocesses.Sort(SJFNeedTimeComparison);  //  前面没执行的的按作业时间
                SJFAftprocesses.Sort(SJFReachTimeComparison);  //  后面的按到达时间

                if (SJFPreprocesses.Count != 0)  //  有当前时间之前到达的进程
                {
                    for (int k = 0; k < proc.Count; k++)
                    {
                        if (proc[k].processPCB.id == SJFPreprocesses[0].processPCB.id)  //  找到这个家伙
                        {
                            proc[k].processPCB.startTime = ProcessManager.Instance.nowTime;
                            proc[k].processPCB.finishTime = proc[k].processPCB.startTime + proc[k].processPCB.needTime;
                            ProcessManager.Instance.nowTime = proc[k].processPCB.finishTime;
                        }
                    }
                }
                else  //  没有当前时间之前到达的进程
                {
                    for (int n = 0; n < proc.Count; n++)
                    {
                        if (proc[n].processPCB.id == SJFAftprocesses[0].processPCB.id)  //  找到这个家伙
                        {
                            proc[n].processPCB.startTime = proc[n].processPCB.reachTime;
                            proc[n].processPCB.finishTime = proc[n].processPCB.startTime + proc[n].processPCB.needTime;
                            ProcessManager.Instance.nowTime = proc[n].processPCB.finishTime;
                        }
                    }
                    //  执行后面第一个
                }
                SJFPreprocesses.Clear();
                SJFAftprocesses.Clear();
            }

    }
}

PF类 优先级调度算法

using simulation.Common;
using simulation.Managers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace simulation.Algorithms
{
    class PF : Singleton<PF>
    {

        Comparison<Process> PFReachTimeComparison = PFReachTimeCompare;
        Comparison<Process> PFPriorityAndReachTimeComparison = PFPriorityAndReachTimeCompare;
        //Comparison<Process> PFPriorityComparison = PFPriorityCompare;

        //private static int PFPriorityCompare(Process x, Process y)
        //{
        //    return y.processPCB.priority.CompareTo(x.processPCB.priority);
        //}

        private static int PFPriorityAndReachTimeCompare(Process x, Process y)
        {
            if(x.processPCB.priority != y.processPCB.priority)
            {
                return y.processPCB.priority.CompareTo(x.processPCB.priority);
            }
            else
            {
                return x.processPCB.reachTime.CompareTo(y.processPCB.reachTime);
            }

        }

        List<Process> PFPreprocesses = new List<Process>();
        List<Process> PFAftprocesses = new List<Process>();

        List<Process> proc = ProcessManager.Instance.processes;

        Process runningProcess;
        Process startProcess;
        List<Process> blockList = new List<Process>();

        private static int PFReachTimeCompare(Process x, Process y)
        {
            return x.processPCB.reachTime.CompareTo(y.processPCB.reachTime);
        }

        public void Init()
        {
            string[] nums;
            string t;

            Console.WriteLine("进程数:");
            string input = Console.ReadLine();
            Console.WriteLine("收到进程数:{0}", input);
            Console.WriteLine("各进程id、到达时间、运行时间、优先级");
            for (int i = 0; i < int.Parse(input); i++)
            {
                t = Console.ReadLine();
                nums = t.Split(new string(" "), StringSplitOptions.None);

                PCB pCB = new PCB();
                pCB.id = nums[0];
                pCB.reachTime = float.Parse(nums[1]);
                pCB.needTime = float.Parse(nums[2]);
                pCB.priority = int.Parse(nums[3]);
                pCB.restTime = pCB.needTime;

                ProcessManager.Instance.processDictionary.Add(pCB.id, pCB);
                ProcessManager.Instance.processes.Add(new Process(pCB));
            }
            Console.WriteLine("抢占式?(Y/N)");
            t = Console.ReadLine();
            if(t == "Y")
            {
                ProcessManager.Instance.PFPreemptive = true;
                for (int i = 0; i < proc.Count; i++)
                {
                    proc[i].processPCB.state = PCB.Status.Ready;
                }
            }

            ProcessManager.Instance.processes.Sort(PFReachTimeComparison);

            ProcessManager.Instance.nowTime = 0;

        }

        public void Start()
        {

            if (ProcessManager.Instance.PFPreemptive)
            {
                PFPreemptiveInit();
                return;
            }

            for (int m =0; m< proc.Count; m++)
            {
                for (int i = 0; i < proc.Count; i++)
                {
                    if (proc[i].processPCB.reachTime <= ProcessManager.Instance.nowTime && proc[i].processPCB.finishTime == 0)
                    {
                        PFPreprocesses.Add(proc[i]);  //  当前时间之前到达的且还未执行的进程放到pre列表里
                    }
                    else if (proc[i].processPCB.reachTime > ProcessManager.Instance.nowTime)
                    {
                        PFAftprocesses.Add(proc[i]);  //  在当前时间之后到达的进程放在aft列表里
                    }
                }

                PFPreprocesses.Sort(PFPriorityAndReachTimeComparison);  //  前面的按优先级和到达时间排
                PFAftprocesses.Sort(PFReachTimeComparison);  //  后面的按到达时间排

                //  非抢占
                if (PFPreprocesses.Count != 0)
                {
                    //  运行列表第一个
                    for (int k = 0; k < proc.Count; k++)
                    {
                        if (proc[k].processPCB.id == PFPreprocesses[0].processPCB.id)  //  找到这个家伙
                        {
                            proc[k].processPCB.startTime = ProcessManager.Instance.nowTime;
                            proc[k].processPCB.finishTime = proc[k].processPCB.startTime + proc[k].processPCB.needTime;
                            ProcessManager.Instance.nowTime = proc[k].processPCB.finishTime;
                        }
                    }
                }
                else
                {
                    //  运行后面列表第一个
                    for (int n = 0; n < proc.Count; n++)
                    {
                        if (proc[n].processPCB.id == PFAftprocesses[0].processPCB.id)  //  找到这个家伙
                        {
                            proc[n].processPCB.startTime = proc[n].processPCB.reachTime;
                            proc[n].processPCB.finishTime = proc[n].processPCB.startTime + proc[n].processPCB.needTime;
                            ProcessManager.Instance.nowTime = proc[n].processPCB.finishTime;
                        }
                    }
                }

                PFPreprocesses.Clear();
                PFAftprocesses.Clear();

            }

        }


        private void PFPreemptiveInit()
        {

            ReFresh();

            if (PFPreprocesses.Count != 0)
            {
                //  运行列表第一个
                for (int k = 0; k < proc.Count; k++)
                {
                    if (proc[k].processPCB.id == PFPreprocesses[0].processPCB.id)  //  找到这个家伙
                    {
                        startProcess = proc[k];
                        RunProcess(proc[k]);  //  让这个进程跑
                        break;
                    }
                }
            }

        }

        private void RunProcess(Process process)
        {
            Console.WriteLine("进程{0}在{1}时刻开始运行", process.processPCB.id, ProcessManager.Instance.nowTime);
            runningProcess = process;
            if(runningProcess.processPCB.startTime == 0 && runningProcess.processPCB.id != startProcess.processPCB.id)
            {
                runningProcess.processPCB.startTime = ProcessManager.Instance.nowTime;
            }
            runningProcess.processPCB.state = PCB.Status.Runing;

            if (IsBlocked())  //  被阻塞了
            {
                RunProcess(runningProcess);
            }
            else  //  没被阻塞
            {
                process.processPCB.finishTime = ProcessManager.Instance.nowTime + process.processPCB.restTime;
                ProcessManager.Instance.nowTime = process.processPCB.finishTime;
                ReFresh();
                process.processPCB.restTime = 0;

                process.processPCB.state = PCB.Status.Destory;
                blockList.Remove(process);
                Console.WriteLine("进程{0}在{1}时刻执行完毕", process.processPCB.id, process.processPCB.finishTime);

                if(blockList.Count != 0)  //  如果有被阻塞的进程
                {
                    blockList.Sort(PFPriorityAndReachTimeComparison);

                    for(int j = 0; j < proc.Count; j++)
                    {
                        if(proc[j].processPCB.id == blockList[0].processPCB.id)
                        {
                            RunProcess(proc[j]);
                            break;
                        }
                    }

                }
                else if(PFAftprocesses.Count != 0)  //  没有被阻塞的进程且后面还有进程,等一段时间后开始
                {
                    ProcessManager.Instance.nowTime = PFAftprocesses[0].processPCB.reachTime;
                    ReFresh();
                    for(int k =0;k < proc.Count; k++)
                    {
                        if(proc[k].processPCB.id == PFAftprocesses[0].processPCB.id)
                        {
                            RunProcess(proc[k]);
                        }
                    }
      
                }
                else
                {
                    Console.WriteLine("所有进程执行完毕");
                }


            }

        }

        public bool IsBlocked()
        {
            for(int i = 0; i< PFAftprocesses.Count; i++)
            {
                if ((PFAftprocesses[i].processPCB.reachTime
                <= runningProcess.processPCB.startTime + runningProcess.processPCB.restTime)
                && PFAftprocesses[i].processPCB.priority > runningProcess.processPCB.priority)  //  不到正在运行进程执行完新进程就会进入且新进程优先级更高
                {
                    runningProcess.processPCB.restTime = runningProcess.processPCB.restTime - (PFAftprocesses[i].processPCB.reachTime - runningProcess.processPCB.startTime);
                    runningProcess.processPCB.state = PCB.Status.Block;
                    blockList.Add(runningProcess);
                    Console.WriteLine("进程{0}在{1}时刻被进程{2}阻塞,restTime:{3}", runningProcess.processPCB.id, PFAftprocesses[i].processPCB.reachTime, PFAftprocesses[i].processPCB.id, runningProcess.processPCB.restTime);


                    for(int n = 0; n < proc.Count; n++)
                    {
                        if (proc[n].processPCB.id == PFAftprocesses[i].processPCB.id)
                        {
                            runningProcess = proc[n];
                            break;
                        }
                    }
                    runningProcess.processPCB.state = PCB.Status.Runing;
                    ProcessManager.Instance.nowTime = runningProcess.processPCB.reachTime;
                    ReFresh();
                    return true;
                }else if ((PFAftprocesses[i].processPCB.reachTime
                <= runningProcess.processPCB.startTime + runningProcess.processPCB.restTime)
                && PFAftprocesses[i].processPCB.priority <= runningProcess.processPCB.priority)   //  不到正在运行进程执行完新进程就会进入但是优先级不足以抢断
                {
                    for (int n = 0; n < proc.Count; n++)
                    {
                        if (proc[n].processPCB.id == PFAftprocesses[i].processPCB.id)
                        {
                            proc[n].processPCB.state = PCB.Status.Block;
                            blockList.Add(proc[n]);
                            Console.WriteLine("进程{0}在时刻{1}尝试抢断失败,进入阻塞状态", proc[n].processPCB.id, proc[n].processPCB.reachTime);
                        }
                    }
                }
            }

            return false;
        }


        public void ReFresh()
        {
            PFPreprocesses.Clear();
            PFAftprocesses.Clear();

            for (int i = 0; i < proc.Count; i++)
            {
                if (proc[i].processPCB.reachTime <= ProcessManager.Instance.nowTime && proc[i].processPCB.restTime != 0)
                {
                    PFPreprocesses.Add(proc[i]);  //  当前时间之前到达的且还未执行完毕的进程放到pre列表里
                }
                else if (proc[i].processPCB.reachTime >= ProcessManager.Instance.nowTime)
                {
                    PFAftprocesses.Add(proc[i]);  //  在当前时间及之后到达的进程放在aft列表里
                }
            }
        }


    }
}

Program区:

Program类

using simulation.Managers;
using System;

namespace simulation
{
    class Program
    {
        bool doItAngin;

        static void Main(string[] args)
        {
            Program program = new Program();
            program.NewMethod();

        }

        private void NewMethod()
        {
            doItAngin = true;

            do
            {
                Console.WriteLine("1:先来先服务调度算法,2:短作业优先调度算法,3:优先级调度算法, 退出:Exit");
                string input = Console.ReadLine();
                switch (input)
                {
                    case "1":
                        ProcessManager.Instance.StartFCFS();
                        break;
                    case "2":
                        ProcessManager.Instance.StartSJF();
                        break;
                    case "3":
                        ProcessManager.Instance.StartPF();
                        break;
                    case "Exit":
                        doItAngin = false;
                        break;
                    default:
                        Console.WriteLine("输入错误,请输入三个数字之一或Exit");
                        break;
                }
            } while (doItAngin);
        }
    }
}

使用方法:

1. 实验目的 调度的实质是操作系统按照某种预定的策略来分配资源。进程调度的目的是分配CPU资源。由于进程调度程序执行的频率很高,因此调度算法的好坏直接影响到操作系统的性能。本实验的目的是编程模拟实现几种常用的进程调度算法,通过对几组进程分别使用不同的调度算法,计算进程的平均周转时间和平均带权周转时间,比较各种算法的性能优劣。 2. 实验原理 [1]. 进程调度算法描述 进程调度算法包括先来先服务调度算法、最作业时间优先抢占抢占)、最高响应比调度算法4种。(每个人必须做FCFS,然后在后面的三种中任选一种,即每个人必须做2种调度算法模拟。) [2]. 衡量算法性能的参数 计算进程的平均周转时间和平均带权周转时间。 3. 实验内容 (1)编程实现本实验的程序,要求: [1]. 建立进程的进程控制块,进程控制块至少包括: a) 进程名称; b) 进程需要执行时间; c) 进入就绪队列时间; d) 进程执行开始时间 e) 进程执行结束时间 [2]. 编程实现调度算法。 [3]. 进程及相关信息的输入。这些信息可以直接从键盘上输入,也可以从文件读取。 [4]. 时间片与时间流逝的模拟。本实验需要对算法的执行计时,程序应该提供计算时间的方法。一种最简单的方法是使用键盘,比如每敲一次空格代表一个时间片的流逝。另一种方法是使用系统时钟。 [5]. 一组进程序列执行完毕,打印出结果信息。程序需要计算出每个进程的开始执行时间、结束时间、周转时间和带权周转时间,并为整个进程序列计算平均周转时间和平均带权周转时间。程序将计算结果按一定的格显示在计算机屏幕上或输出到文件中。打印出进程调度顺序图。 [6]. 实现数据在磁盘文件上的存取功能。 (2)对下列就绪进程序列分别使用上面的几种算法进行调度,计算每种算法下的平均周转时间和平均带权周转时间。 进程号 到达时间 要求执行时间 0 0 1 1 1 35 2 2 10 3 3 5 4 6 9 5 7 21 6 9 35 7 11 23 8 12 42 9 13 1 10 14 7 11 20 5 12 23 3 13 24 22 14 25 31
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值