计算机操作系统可视化的四大算法设计(调度算法,银行家算法,置换算法,磁盘调度算法)

这是整合在一起的算法是我的期末作品,可能页面设计过于简单,仅供学习参考。


话不多数直接先上运行效果:


在这里插入图片描述
在这里插入图片描述
进程调度算法:
在这里插入图片描述
银行家算法:
在这里插入图片描述
页面置换算法:
在这里插入图片描述
磁盘调度算法:
在这里插入图片描述
在这里插入图片描述

算法核心代码:

银行家算法:

package Banker;

public class Banker {
    private int numResource = 3;
    private int numThread = 100;
    private int p = 0; // 当前处理的线程
    int[] Available = new int[numResource]; // 空闲资源
    int[][] Max = new int[numThread][numResource]; // 最大需求资源
    int[][] Allocation = new int[numThread][numResource]; // 占有资源
    int[][] Need = new int[numThread][numResource]; // 需求资源
    int[][] Request = new int[numThread][numResource]; // 申请资源
    int[] Work = new int[numResource]; // 辅助空间

    public void handle_input(int p00,int p01,int p02,int p03,int p04,int p05,int p06,int p07,int p08,int p09,int p010,int p011,int p10,int p11,int p12,int p13,int p14,int p15,int p16,int p17,int p18,int p20,int p21,int p22,int p23,int p24,int p25,int p26,int p27,int p28,int p30,int p31,int p32,int p33,int p34,int p35,int p36,int p37,int p38,int input_a,int input_b,int input_c){
        Max[0][0]=p00;
        Max[0][1]=p01;
        Max[0][2]=p02;
        Max[1][0]=p10;
        Max[1][1]=p11;
        Max[1][2]=p12;
        Max[2][0]=p20;
        Max[2][1]=p21;
        Max[2][2]=p22;
        Max[3][0]=p30;
        Max[3][1]=p31;
        Max[3][2]=p32;

        Allocation[0][0]=p03;
        Allocation[0][1]=p04;
        Allocation[0][2]=p05;
        Allocation[1][0]=p13;
        Allocation[1][1]=p14;
        Allocation[1][2]=p15;
        Allocation[2][0]=p23;
        Allocation[2][1]=p24;
        Allocation[2][2]=p25;
        Allocation[3][0]=p33;
        Allocation[3][1]=p34;
        Allocation[3][2]=p35;

        Need[0][0]=p06;
        Need[0][1]=p07;
        Need[0][2]=p08;
        Need[1][0]=p16;
        Need[1][1]=p17;
        Need[1][2]=p18;
        Need[2][0]=p26;
        Need[2][1]=p27;
        Need[2][2]=p28;
        Need[3][0]=p36;
        Need[3][1]=p37;
        Need[3][2]=p38;

        Available[0]=p09;
        Available[0]=p10;
        Available[0]=p11;

        Request[0][0]=input_a;
        Request[0][1]=input_b;
        Request[0][2]=input_c;


    }
    // 算法核心流程
    public boolean bankerKernel(int num, int[] order){
        // 判断资源申请的数量是否符合空闲资源和需要资源
        for(int i = 0; i < numResource; i++){
            if(Request[num][i] > Need[num][i]) {
                System.out.println("错误:进程P" + num + "的申请,超出最大需求量Need。");
                return false;
            }
            else if(Request[num][i] > Available[i]){
                System.out.println("错误:当前没有足够的资源可申请,进程P" + num + "需等待。");
                return false;
            }
        }
        // 更新空闲资源,占用资源和需要资源
        for (int i = 0; i < numResource; i++) {
            Allocation[num][i] += Request[num][i];
            Available[i] -= Request[num][i];
            Need[num][i] -= Request[num][i];
        }
        // 安全性检查
        if(isSafe(order)){
            return true;
        }
        // 不安全,返回申请资源前的状态
        for (int i = 0; i < numResource; i++) {
            Allocation[num][i] -= Request[num][i];
            Available[i] += Request[num][i];
            Need[num][i] += Request[num][i];
        }
        return false;
    }
    // 安全性检查
    public boolean isSafe(int[]order){
        int count = 0; // 安全的线程数量
        int k = 0;
        int circle = 0; // 循环次数
        boolean[] Finish = new boolean[numThread]; // 线程是否进入安全序列
        for (int i = 0; i < numResource; i++) {
            Finish[i] = false;
        }
        copyWork();
        while(true){
            for (int i = 0; i < numThread; i++) {
                if(Finish[i] == false){
                    for (k = 0; k < numResource; k++) {
                        if(Work[k] < Need[i][k])
                            break;
                    }
                    // 空闲资源满足线程所需要的资源
                    if(k == numResource){
                        order[count++] = i;
                        Finish[i] = true;
                        // 释放资源
                        for (int j = 0; j < numResource; j++) {
                            Work[j] += Allocation[i][j];
                        }
                    }
                }
            }
            circle++;
            if(count == numThread){
                System.out.print("存在一个安全序列:");
                for (int i = 0; i < numThread; i++){//输出安全序列
                    System.out.print("P" + order[i] + " ");
                }
                System.out.println("故当前可分配!");
                return true;
            }
            // 如果进入安全序列的线程数小于循环次数,说明不存在能安全完成的线程
            if(count < circle){
                System.out.println("警告:申请使得系统处于不安全状态,申请失败。");
                return false;
            }
        }
    }
    // 使用辅助空间
    public void copyWork(){
        for (int i = 0; i < numResource; i++) {
            Work[i] = Available[i];
        }
    }
    // 清零
    public void reset(){
        for (int i = 0; i < numThread; i++) {
            for (int j = 0; j < numResource; j++) {
                Max[i][j] = 0;
                Allocation[i][j] = 0;
                Need[i][j] = 0;
                Available[j] = 0;
            }
        }
    }
    // 撤回
    public boolean revocation(){
        if(Request[p][0] == 0 && Request[p][1] == 0 && Request[p][2] == 0)
            return false;
        for (int i = 0; i < numResource; i++) {
            Allocation[p][i] -= Request[p][i];
            Need[p][i] = Max[p][i] - Allocation[p][i];
            Available[i] += Request[p][i];
            Request[p][i] = 0;
        }
        return true;
    }
}

磁盘调度算法:

package DISC;

import javax.swing.*;

public class SSTFandSCANandCSCAN {

    int nowN;//当前磁道
    int[] arrD;//排序后的数组
    public void handle_Input(String str,int num ){
        this.nowN=num;
        String[] arrS=str.split(",");
        //字符串->int
        arrD=new int[arrS.length];//不能为null
        for(int i=0;i< arrS.length;i++){
            //System.out.println(arrS[i]);
            arrD[i]=Integer.valueOf(arrS[i]);
        }
        //冒泡排序
        int t;
        for (int i=0; i<arrD.length-1; i++) { /* 外循环为排序趟数,len个数进行len-1趟 */
            for (int j = 0; j < arrD.length - 1 - i; j++) { /* 内循环为每趟比较的次数,第i趟比较len-i次 */
                if (arrD[j] > arrD[j + 1]) { /* 相邻元素比较,若逆序则交换(升序为左大于右,降序反之) */
                    t = arrD[j];
                    arrD[j] = arrD[j + 1];
                    arrD[j + 1] = t;
                }
            }
        }
        //55,58,39,18,90,160,150,38,184
        /*for(int i=0;i<arrD.length;i++){
            System.out.println(arrD[i]+" ");
        }*/

    }

    int sign;
    //重载(扫描的那方向选择)
    public void handle_Input(String str,int num,int sign ){
        this.nowN=num;
        this.sign=sign;
        String[] arrS=str.split(",");
        //字符串->int
        arrD=new int[arrS.length];//不能为null
        for(int i=0;i< arrS.length;i++){
            //System.out.println(arrS[i]);
            arrD[i]=Integer.valueOf(arrS[i]);
        }
        //冒泡排序
        int t;
        for (int i=0; i<arrD.length-1; i++) { /* 外循环为排序趟数,len个数进行len-1趟 */
            for (int j = 0; j < arrD.length - 1 - i; j++) { /* 内循环为每趟比较的次数,第i趟比较len-i次 */
                if (arrD[j] > arrD[j + 1]) { /* 相邻元素比较,若逆序则交换(升序为左大于右,降序反之) */
                    t = arrD[j];
                    arrD[j] = arrD[j + 1];
                    arrD[j + 1] = t;
                }
            }
        }
        //55,58,39,18,90,160,150,38,184
        /*for(int i=0;i<arrD.length;i++){
            System.out.println(arrD[i]+" ");
        }*/

    }
    public String SSTF(){

        String s="";
        int sumL=0;
        double ave;

        int len=arrD.length;

        String s1="";
        for(int i=0;i<len;i++){
            s1+=arrD[i]+" ";
        }
        s+="磁道序列从小到大排序为:\n"+s1+"\n\n";
        if(arrD[len-1]<=nowN){  //若当前磁道号大于请求序列中最大者,则直接由外向内依次给予各请求服务
            String s2="";
            sumL=0;

            for(int i=len-1;i>=0;i--){
                s2+=arrD[i]+" ";
            }
            s+="磁盘扫描序列为: \n"+s2+"\n\n";
            sumL=nowN-arrD[0];
        }

        if(arrD[0]>=nowN){ //若当前磁道号小于请求序列中最小者,则直接由内向外依次给予各请求服务;
            String s2="";
            sumL=0;

            for(int i=0;i<len;i++){
                s2+=arrD[i]+" ";
            }
            s+="磁盘扫描序列为: \n"+s2+"\n\n";
            sumL=arrD[len-1]-nowN;
        }

        if(nowN>arrD[0]&&nowN<arrD[len-1]) {//若当前磁道号大于当前请求序列中最小者并且小于最大者
            String s2="";
            sumL=0;
            int k=1;
            int  l,r=0;
            while(arrD[k]<nowN){   //确定当前磁道在已排的序列中的位置
                k++;
            }
            l=k-1;
            r=k;
            while((l>=0)&&(r<len)){ //当前磁道在请求序列范围内
                if(nowN-arrD[l]<=(arrD[r]-nowN)) {//选择与当前磁道最近的请求给予服务
                    s2+=arrD[l]+" ";
                    sumL+=nowN-arrD[l];
                    nowN=arrD[l];
                    l=l-1;
                }
                else{
                    s2+=arrD[r]+" ";
                    sumL+=arrD[r]-nowN;
                    nowN=arrD[r];
                    r=r+1;
                }
            }
            if(l==-1) {//磁头移动到序列的最小号,返回外侧扫描仍未扫描的磁道
                for(int j=r;j<len;j++){
                    s2+=arrD[j]+" ";
                }
                sumL+=arrD[len-1]-arrD[0];
            }
            else{ //磁头移动到序列的最大号,返回内侧扫描仍未扫描的磁道
                for(int j=l;j>=0;j--){
                    s2+=arrD[j]+" ";
                }
                sumL+=arrD[len-1]-arrD[0];
            }
            s+="磁盘扫描序列为: \n"+s2+"\n\n";
        }

        ave=(double)sumL/len;
        s+="平均寻道长度:"+ave;
        //s+="长度:"+sumL;
        return s;
    }

    public String SCAN(){

        String s="";
        int sumL=0;
        double ave;

        int len=arrD.length;

        //输出排序后的数组
        String s1="";
        for(int i=0;i<len;i++){
            s1+=arrD[i]+" ";
        }
        s+="磁道序列从小到大排序为:\n"+s1+"\n\n";

        //若当前磁道号大于请求序列中最大者,则直接由外向内
        if(arrD[len-1]<=nowN){
            s1="";
            for(int i=len-1;i>=0;i--){
                s1+=arrD[i]+" ";
            }
            s+="磁盘扫描序列为:\n"+s1+"\n\n";
            sumL=nowN-arrD[0];
        }

        //若当前磁道号小于请求序列中最小者,则直接由内向外
        if(arrD[0]>=nowN){
            s1="";
            for(int i=0;i<len;i++){
                s1+=arrD[i]+" ";
            }
            s+="磁盘扫描序列为:\n"+s1+"\n\n";
            sumL=arrD[len-1]-nowN;
        }


        //若当前磁道号大于请求序列中最小者且小于最大者
        int k=1;
        int l,r=0;

        if(nowN>arrD[0]&&nowN<arrD[len-1]){
            s1="";
            while(arrD[k]<nowN){
                k++;
            }
            l=k-1;
            r=k;

            if(sign==0){  //选择移动臂方向向内,则先向内扫描

                for(int j=l;j>=0;j--){

                    s1+=arrD[j]+" ";
                }
                for(int j=r;j<len;j++){  //磁头移动到最小号,则改变方向向内扫描为扫描的磁道
                    s1+=arrD[j]+" ";
                }
                sumL=nowN-2*arrD[0]+arrD[len-1];
            }
            else{ //选择移动臂方向向外,则先向外扫描

                for(int j=r;j<len;j++){
                    s1+=arrD[j]+" ";
                }
                for(int j=l;j>=0;j--){
                    s1+=arrD[j]+" ";
                }
                sumL=-nowN-arrD[0]+2*arrD[len-1];
            }
            s+="磁盘扫描序列为:\n"+s1+"\n\n";


        }
        ave= (double)sumL/len;
        s+="平均寻道长度:"+ave;

        return s;
    }

    public String CSCAN(){
    	  String s="";
          int sumL=0;
          double ave;
          int len=arrD.length;
          //输出排序后的数组
          String s1="";
          for(int i=0;i<len;i++){
              s1+=arrD[i]+" ";
          }
          s+="磁道序列从小到大排序为:\n"+s1+"\n\n";

          //若当前磁道号大于请求序列中最大者,则直接由外向内
          if(arrD[len-1]<=nowN){
              s1="";
              for(int i=len-1;i>=0;i--){
                  s1+=arrD[i]+" ";
              }
              s+="磁盘扫描序列为:\n"+s1+"\n\n";
              sumL=nowN-arrD[0];
          }

          //若当前磁道号小于请求序列中最小者,则直接由内向外
          if(arrD[0]>=nowN){
              s1="";
              for(int i=0;i<len;i++){
                  s1+=arrD[i]+" ";
              }
              s+="磁盘扫描序列为:\n"+s1+"\n\n";
              sumL=arrD[len-1]-nowN;
          }


          //若当前磁道号大于请求序列中最小者且小于最大者
          int k=1;
          int l,r=0;

          if(nowN>arrD[0]&&nowN<arrD[len-1]){
              s1="";
              while(arrD[k]<nowN){
                  k++;
              }
              l=k-1;
              r=k;

              if(sign==0){  //选择移动臂方向向内,则先向内扫描

                  for(int j=l;j>=0;j--){

                      s1+=arrD[j]+" ";
                  }
                  for(int j=len-1;j>=r;j--){  //磁头移动到最小号,则改变方向向内扫描为扫描的磁道
                      s1+=arrD[j]+" ";
                  }
                  //sumL=arrD[len-1]-arrD[0]+arrD[l]-arrD[0]+arrD[len-1]-nowN;
                  //sumL=(arrD[len-1]-arrD[0]+nowN)*2-arrD[len-1]-arrD[];
                  sumL=arrD[len-1]-arrD[0]+nowN-arrD[0]+arrD[len-1]-arrD[r];
              }
              else{ //选择移动臂方向向外,则先向外扫描

                  for(int j=r;j<len;j++){
                      s1+=arrD[j]+" ";
                  }
                  for(int j=0;j<=l;j++){
                      s1+=arrD[j]+" ";
                  }
                  sumL=arrD[len-1]-arrD[0]+arrD[l]-arrD[0]+arrD[len-1]-nowN;
                  //System.out.println(sumL);
              }
              s+="磁盘扫描序列为:\n"+s1+"\n\n";
          }
          ave= (double)sumL/len;
          s+="平均寻道长度:"+ave;

          return s;
    	/*                       */
     /*  String s="";
        int sumL=0;
        double ave;

        int len=arrD.length;

        //输出排序后的数组
        String s1="";
        for(int i=0;i<len;i++){
            s1+=arrD[i]+" ";
        }
        s+="磁道序列从小到大排序为:\n"+s1+"\n\n";

        //若sign信号为1,则由外向内
        if(sign==1){
            s1="";
            for(int i=len-1;i>=0;i--){
                s1+=arrD[i]+" ";
            }
            s+="磁盘扫描序列为:\n"+s1+"\n\n";
            sumL=nowN-arrD[0]+arrD[len-1]-arrD[0];
        }
        else{//由内向外
            s1="";
            for(int i=0;i<len;i++){
                s1+=arrD[i]+" ";
            }
            s+="磁盘扫描序列为:\n"+s1+"\n\n";
            sumL=arrD[len-1]-nowN+arrD[len-1]-arrD[0];
        }

        ave= (double)sumL/len;
        s+="平均寻道长度:"+ave;

        return s;*/
    }
}

进程调度算法:

package Dispatch;

public class FCFSandSJF {
    Process p[];
    int number;
    String opt;
    public void handle_Input(int number,String Proname,String arr,String ser){
        this.number=number;
        //p=new Process[number];
        String name[]=Proname.split(",");

        String arrS[]=arr.split(",");
        Double arrD[]=new Double[arrS.length];//不能为null
        for(int i=0;i< arrS.length;i++){
            //System.out.println(arrS[i]);
            arrD[i]=Double.valueOf(arrS[i]);
        }

        String serS[]=ser.split(",");
        Double serD[]=new Double[serS.length];
        for(int i=0;i< serS.length;i++){
            serD[i]=Double.valueOf(serS[i]);
        }

        p=new Process[number];
        for(int i=0;i<number;i++){
            p[i]=new Process(name[i],arrD[i],serD[i]);
        }
    }

    public String FCFS(){
        for(int i=0;i<number;i++){
            if(i==0){
                p[i].arrT=0;
                p[i].finishT=p[i].workT;
                p[i].cyclingT=p[i].finishT-0;
                p[i].weightT=p[i].cyclingT/p[i].workT;
            }else{
                if(p[i].arrT<p[i-1].finishT)
                    p[i].startT=p[i-1].finishT;
                else
                    p[i].startT=p[i].arrT;
                p[i].finishT=p[i].workT+p[i].startT;
                p[i].cyclingT=p[i].finishT-p[i].arrT;
                p[i].weightT=p[i].cyclingT/p[i].workT;
            }
            System.out.println("进程"+p[i].name+"完成");
        }

        String s="进程的名称\t到达时间\t工作时间\t开始时间\t完成时间\t周转时间\t带权周转时间\n";
        double sum=0;
        double aveT;//平均周转时间
        for(int i=0;i<number;i++){
            s+="    "+p[i].name+"\t";
            s+="  "+p[i].arrT+"\t";
            s+="  "+p[i].workT+"\t";
            s+="  "+p[i].startT+"\t";
            s+="  "+p[i].finishT+"\t";
            s+="  "+p[i].cyclingT+"\t";
            s+="  "+String.format("%.2f",p[i].weightT);
            s+="\n";
            sum+=p[i].cyclingT;
        }
        
        System.out.print(sum);
        aveT=sum/number;
        s+="\n平均周转时间\n"+aveT;

        return s;
    }
    public String SJF(){

        Process p1[]=new Process[1];

        for(int i=p.length-1;i>1;i--){//4,3,2
            for(int j=1;j<i;j++){//1,2,3   1,2  ,1
                if(p[j].workT>p[j+1].workT){//12,23,34  12,23 12
                    p1[0]=p[j];
                    p[j]=p[j+1];
                    p[j+1]=p1[0];
                }
            }
        }
        //String s=this.FCFS();
        return this.FCFS();
    }
}

页面置换算法:

package Displace;

import java.util.*;

public class OPTandFIFOandLRU {

    String streamStr=null;
    int number = 0;

    private int n;//块数
    private int m;//访问次数
    private int F;//没能直接找到的次数,(F/m)为缺页率
    private List<Integer> list=null;//访问地址走向
    private Map<Integer,Integer>map=null;

    public void handle_Input(String stream,int num){
        this.streamStr=stream;
        this.number=num;
    }


    public String OPT(){
        String str="访问页面流:"+streamStr+"\n"+"内储叶框数:"+number+"\n\n";
        map=new HashMap<Integer,Integer>();//存储每一个块所存的内容
        list=new ArrayList<Integer>();
        String s=streamStr;
        String []s1=s.split(",");
        m=s1.length;
        for (int i=0;i<m;i++)
            list.add(Integer.valueOf(s1[i]));
        n=number;
        int j;
        for (int i=0;i<m;i++)
        {
            int k=list.get(i);//待处理元素
            //System.out.print(map);
            if (!map.containsValue(k)){
                F++;//不能直接找到次数加1
                if (map.size()<n){//如果没有装满
                    str+="第"+(i+1)+"次访问页面,第"+k+"页被调入内存\n";

                    int temp=map.size();
                    map.put(temp, k);
                }
                else{//如果装满了
                    int index=0;//把哪个位置的淘汰出去
                    int min=0;//初始最长长度
                    for (int t=0;t<n;t++)
                    {
                        for (j=i+1;j<m;j++){//看后面哪一个出现的最晚
                            if (list.get(j)==map.get(t)){//第一次找到
                                if (j-i>min){
                                    index=t;//更新值
                                    min=j-i;
                                }

                                break;
                            }
                        }
                        if (j==m){//如果到最后
                            index=t;
                            min=j-i;
                        }
                    }
                    map.remove(index);
                    map.put(index,k);//修改表内元素
                    str+="第"+(i+1)+"次访问页面,第"+index+"页被置换,"+"第"+k+"页被调入内存\n";
                }
            }
            else {
                str+="第"+(i+1)+"次访问页面,第"+k+"页被调入内存\n";
            }
        }
        str+="\n\n缺页率为:"+F*1.0/m+"\n";
        return str;
    }
    public  String FIFO(){
        String str="访问页面流:"+streamStr+"\n"+"内储叶框数:"+number+"\n\n";
        map=new HashMap<Integer,Integer>();//存储每一个块所存的内容
        list=new ArrayList<Integer>();
        String s=streamStr;
        String []s1=s.split(",");
        m=s1.length;
        for (int i=0;i<m;i++)
            list.add(Integer.valueOf(s1[i]));
        n=number;
        Queue<Integer>q=new LinkedList<Integer>();

        for (int i=0;i<m;i++)
        {
            int k=list.get(i);//待处理元素
            if (!map.containsValue(k)){
                F++;//不能直接找到次数加1
                if (map.size()<n){//如果没有装满
                    int temp=map.size();
                    map.put(temp, k);
                    q.offer(temp);
                    str+="第"+(i+1)+"次访问页面,第"+k+"页被调入内存\n";
                }
                else
                {
                    int temp=q.poll();//排除的元素位置
                    map.remove(temp);
                    map.put(temp,k);
                    q.offer(temp);
                    str+="第"+(i+1)+"次访问页面,第"+temp+"页被置换,"+"第"+k+"页被调入内存\n";
                }
            }
            else {
                str+="第"+(i+1)+"次访问页面,第"+k+"页被调入内存\n";
            }
        }
        str+="\n\n缺页率为:"+F*1.0/m+"\n";
        return str;
    }

    public  String LRU(){
        String str="访问页面流:"+streamStr+"\n"+"内储叶框数:"+number+"\n\n";
        map=new HashMap<Integer,Integer>();//存储每一个块所存的内容
        list=new ArrayList<Integer>();
        String s=streamStr;
        String []s1=s.split(",");
        m=s1.length;
        for (int i=0;i<m;i++)
            list.add(Integer.valueOf(s1[i]));
        n=number;
        List<Integer>linkedlist=new LinkedList<Integer>();

        for (int i=0;i<m;i++)
        {
            int k=list.get(i);//待处理元素
            if (!map.containsKey(k)){
                F++;//不能直接找到次数加1
                if (map.size()<n){//如果没有装满
                    int temp=map.size();
                    map.put(k,temp);
                    linkedlist.add(k);//添加位置
                    str+="第"+(i+1)+"次访问页面,第"+k+"页被调入内存\n";
                }
                else
                {
                    int temp=linkedlist.get(0);
                    int c=map.get(temp);//位置
                    map.remove(temp);
                    map.put(k,c);
                    linkedlist.remove(0);
                    linkedlist.add(k);
                    str+="第"+(i+1)+"次访问页面,第"+temp+"页被置换,"+"第"+k+"页被调入内存\n";
                }
            }
            else//如果包含这个值,把这个值拿走并在后面压入
            {
                int d=linkedlist.indexOf(k);//查找存在位置
                linkedlist.remove(d);
                linkedlist.add(k);
                str+="第"+(i+1)+"次访问页面,第"+d+"页被置换,"+"第"+k+"页被调入内存\n";
            }
        }
        str+="\n\n缺页率为:"+F*1.0/m+"\n";
        return str;
    }
}

算法我可能写的比较low,可以自行优化。源码后期会上传(还不知道怎么上传源码)。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZeroBase.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值