检索算法的实现——顺序检索、二分检索、三分检索

实验II: 检索算法的实现

本次实验拟解决生活中最常见的问题之一:检索问题(查找问题),该问题要求在一个列表中查找某个具体元素是否出现,若出现,返回具体元素在数组中的位置,否则返回-1。根据列表中元素的相对大小信息,有顺序检索、二分检索、三分检索等算法思路可供参考使用,本次实验需要学生根据所给列表的性质采取有效算法解决相关问题,并能分析各个算法所使用的算法设计技术和时间复杂度。下列基本要求必须完成:

  1. 设计一个交互界面(例如菜单)供用户选择,如果可能,最好是一个图形化用户界面;
  2. 能够人工输入或随机产生一个长度为n的整数数组,要求数组任意两个元素都互不相同;
  3. 设计一个算法判断要求2中产生的整数数组是否为或未排序(输出0)、升序(输出1)、降序(输出2)、先升后降(输出3)、或先降后升(输出4)状态;
  4. 给定某具体元素,使用顺序检索算法判断该具体元素是否出现在要求2中产生的数组中,并统计关键字比较的次数;
  5. 给定某具体元素,使用二分检索算法判断该具体元素是否出现在要求2中产生的升序或降序的数组中,并统计关键字比较的次数;
  6. 给定某具体元素,使用三分检索算法判断该具体元素是否出现在要求2中产生的升序或降序的数组中,并统计关键字比较的次数;
  7. 给定先升后降(或先降后升)数组,使用二分检索思路查找该数组的最大值(或最小值),并统计关键字比较的次数。

附加:给定某具体元素,使用二分检索算法判断该具体元素是否出现在要求2中产生的升序或降序的数组中,若出现,返回具体元素所在的位置,否则,返回小于最接近该具体元素的位置。

searchSuanfa.java

package com;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

import javax.swing.JOptionPane;
import javax.swing.JTextArea;

public class searchSuanfa {
	
	private static int compareCount=0;
	
	
	
	//选择生成数组算法
	public static int[] ChooseGenerateArray() {
	    int i = Integer.parseInt(JOptionPane.showInputDialog("选择生成数组方式(自动1 人工2 升序3 降序4"));
	    int[] result = null;
	    
	    switch (i) {
	        case 1:
	            result = generateArray();
	            break;
	        case 2:
	            result = renGongArray();
	            break;
	        case 3:
	            result = generateRandomSortedArray(true);
	            break;
	        case 4:
	            result = generateRandomSortedArray(false);
	            break;
	    }
	    
	    return result;
	}
	
	//生成数组
    public static int[] generateArray() {
        int n = Integer.parseInt(JOptionPane.showInputDialog("输入数组的长度:"));
        int[] arr = new int[n];
        Random rand = new Random();

        Set<Integer> set = new HashSet<>();
        for (int i = 0; i < n; i++) {
            int num;
            do {
                num = rand.nextInt(2 * n); // 产生0到2n之间的随机数
            } while (set.contains(num)); // 检查是否已经存在该数

            arr[i] = num;
            set.add(num);
        }

        System.out.println("生成数组:");
        for (int value : arr) {
            System.out.print(value + " ");
        }
        System.out.println("\n");
        return arr;
    }
    

    //人工生成数组
    public static int[] renGongArray() {
        int length = Integer.parseInt(JOptionPane.showInputDialog("输入数组的长度:"));

        JTextArea textArea = new JTextArea(length, 1);
        JOptionPane.showMessageDialog(null, textArea, "请输入数组元素(每个元素一空格):", JOptionPane.INFORMATION_MESSAGE);

        String[] lines = textArea.getText().split("\\s+");//使用split("\\s+")方法根据一个或多个连续的空格来拆分字符串
        int[] array = new int[length];
             
        System.out.println("生成数组:");
        for (int i = 0; i < length; i++) {
            array[i] = Integer.parseInt(lines[i].trim());
            System.out.print(array[i]);
        }
        System.out.println("\n");
        return array;
    }
    
    // true 为升序,false 为降序,n为数组长度
    public static int[] generateRandomSortedArray(boolean ascending) {
    	int n=Integer.parseInt(JOptionPane.showInputDialog("输入数组的长度:"));
        int[] array = new int[n];
        
        // 随机生成未排序的数组
        for (int i = 0; i < n; i++) {
            array[i] = i + 1;
        }
        shuffleArray(array);

        // 对数组进行排序
        if (!ascending) {
            Arrays.sort(array);
            reverseArray(array);
        } else {
            Arrays.sort(array);
        }
        
        return array;
    }

    // 随机打乱数组
    private static void shuffleArray(int[] array) {
        Random random = new Random();
        for (int i = array.length - 1; i > 0; i--) {
            int index = random.nextInt(i + 1);
            int temp = array[index];
            array[index] = array[i];
            array[i] = temp;
        }
    }

    // 反转数组
    private static void reverseArray(int[] array) {
        for (int i = 0; i < array.length / 2; i++) {
            int temp = array[i];
            array[i] = array[array.length - 1 - i];
            array[array.length - 1 - i] = temp;
        }
    }
    
    
    
    //此函数首先调用countTurningPoints函数来计算数组中的转折点数量
    //如果转折点数量为0,它会检查数组是否严格升序(第一个元素小于最后一个元素)或严格降序(第一个元素大于最后一个元素)
    //如果转折点数量为1,它会找到这个转折点,然后检查数组是否先升后降或先降后升
    //如果转折点数量大于1,或者没有符合先升后降或先降后升的情况,函数会返回0,表示数组未排序
    public static int checkArrayStatus(int[] array) {
        int turningPoints = countTurningPoints(array);

        if (turningPoints == 0) {
            if (array[0] < array[array.length - 1]) {
                return 1; // 升序
            } else if (array[0] > array[array.length - 1]) {
                return 2; // 降序
            }
        } else if (turningPoints == 1) {//只有一次转折
            int turningIndex = findTurningIndex(array);
            if (turningIndex > 0 && turningIndex < array.length - 1) {
                if (array[0] < array[turningIndex] && array[turningIndex] > array[array.length - 1]) {//判断峰值和初末值大小,判断先升后降
                    return 3; // 先升后降
                } else if (array[0] > array[turningIndex] && array[turningIndex] < array[array.length - 1]) {//判断波谷值和初末值大小,判断先升后降
                    return 4; //先降后升
                }
            }
        }

        return 0; // 未排序
    }


    
    //这个函数通过遍历数组来计算转折点的数量
    //转折点被定义为一个索引,其前一个元素与后一个元素的关系发生变化(例如,从升序变为降序或反之)
    //函数返回转折点的数量
    public static int countTurningPoints(int[] array) {
        int turningPoints = 0;
        for (int i = 1; i < array.length - 1; i++) {
            if ((array[i-1] < array[i] && array[i] > array[i+1]) || (array[i-1] > array[i] && array[i] < array[i+1])) {//顶峰或波谷
                turningPoints++;
            }
        }
        return turningPoints;
    }

    //这个函数返回数组中的第一个转折点的索引
    //转折点是一个索引,其前后元素的关系发生变化
    //如果没有找到转折点,则返回-1
    public static int findTurningIndex(int[] array) {
        for (int i = 1; i < array.length - 1; i++) {
            if ((array[i-1] < array[i] && array[i] > array[i+1]) || (array[i-1] > array[i] && array[i] < array[i+1])) {
                return i;
            }
        }
        return -1; //没有找到索引
    }
    
    
    //查找数
    public static void searchElement(int[] arr ,int i) {
            	
        compareCount = 0;
        int position;
        int numComparisons;
        boolean position1;
        int[] comparisons = { 0 };
        
        switch (i) {
            case 1:
            	 //顺序查找
            	String input = JOptionPane.showInputDialog("输入要查询的元素:");
                int target = Integer.parseInt(input);
                position = sequentialSearch(arr, target);
                if (position == -1) {
                	JOptionPane.showMessageDialog(null, "元素没有找到!");
                    System.out.println("\n元素没有找到!");
                } else {
                	JOptionPane.showMessageDialog(null, position, "找到元素的位置", JOptionPane.INFORMATION_MESSAGE);
                    System.out.println("找到元素的位置: " + position);
                }
                JOptionPane.showMessageDialog(null, compareCount, "关键字比较次数", JOptionPane.INFORMATION_MESSAGE);
                System.out.println("关键字比较次数: " + compareCount);
                break;
            case 2:
            	//二分查找
//                compareCount = 0;
            	input = JOptionPane.showInputDialog("输入要查询的元素:");
                target = Integer.parseInt(input);
                position = binarySearch(arr, target, 0, arr.length - 1);
                if (position == -1) {
                	JOptionPane.showMessageDialog(null, "元素没有找到!");
                    System.out.println("\n元素没有找到!");
                } else {
                	JOptionPane.showMessageDialog(null, position, "找到元素的位置", JOptionPane.INFORMATION_MESSAGE);
                    System.out.println("找到元素的位置: " + position);
                }
                JOptionPane.showMessageDialog(null, compareCount, "关键字比较次数", JOptionPane.INFORMATION_MESSAGE);
                System.out.println("关键字比较次数: " + compareCount);
                break;
            case 3:
            	//三分查找
//                compareCount = 0;
                int[] comparisons1 = { 0 };
            	input = JOptionPane.showInputDialog("输入要查询的元素:");
                target = Integer.parseInt(input);
                position1 = ternarySearch(arr, target, comparisons1);
                numComparisons = comparisons1[0];
                if (position1==false) {
                	JOptionPane.showMessageDialog(null, "元素没有找到!");
                    System.out.println("\n元素没有找到!");
                } else {
                	JOptionPane.showMessageDialog(null, "元素在数组中!");
                    System.out.println("元素在数组中!" );
                }
                JOptionPane.showMessageDialog(null, numComparisons, "关键字比较次数", JOptionPane.INFORMATION_MESSAGE);
                System.out.println("关键字比较次数: " + numComparisons);
                break;
            case 4:
            	//二分查找最大值
            	boolean findMax = true;//最大值 findMax 的值设为 true 最小值 findMax 的值设为 false
                position = findExtremeValue(arr, findMax, comparisons);
                numComparisons = comparisons[0];
                
                JOptionPane.showMessageDialog(null, position, "最大值:", JOptionPane.INFORMATION_MESSAGE);
                System.out.println("最大值:" + position);
                
                JOptionPane.showMessageDialog(null, numComparisons, "关键字比较次数", JOptionPane.INFORMATION_MESSAGE);
                System.out.println("关键字比较次数:" + numComparisons);
                break;
            case 5:
            	//二分查找最小值
            	boolean findMin = false;//最大值 findMax 的值设为 true 最小值 findMax 的值设为 false
                position = findExtremeValue(arr, findMin, comparisons);
                numComparisons = comparisons[0];
                
                JOptionPane.showMessageDialog(null, position, "最小值:", JOptionPane.INFORMATION_MESSAGE);
                System.out.println("最小值:" + position);
                
                JOptionPane.showMessageDialog(null, numComparisons, "关键字比较次数", JOptionPane.INFORMATION_MESSAGE);
                System.out.println("关键字比较次数:" + numComparisons);
                break;
           case 6:
        	   input = JOptionPane.showInputDialog("输入要查询的元素:");
               target = Integer.parseInt(input);
               position = binarySearch(arr, target);
               if (position == -1) {
            		JOptionPane.showMessageDialog(null, position, "接近元素的位置", JOptionPane.INFORMATION_MESSAGE);
                    System.out.println("接近元素的位置: " + position);
               } else {
               		JOptionPane.showMessageDialog(null, position, "找到元素的位置", JOptionPane.INFORMATION_MESSAGE);
                    System.out.println("找到元素的位置: " + position);
               }
               JOptionPane.showMessageDialog(null, compareCount, "关键字比较次数", JOptionPane.INFORMATION_MESSAGE);
               System.out.println("关键字比较次数: " + compareCount);
               break;
//            default:
//                System.out.println("其他");
        }
        
    }

    
    
    //顺序查找算法
    public static int sequentialSearch(int[] arr, int target) {
        for (int i = 0; i < arr.length; i++) {
            compareCount++;
            if (arr[i] == target) {
                return i;
            }
        }
        return -1;
    }


    //二分查找算法
    public static int binarySearch(int[] arr, int target, int left, int right) {
        if (left > right) {
            return -1;
        }

        int mid = left + (right - left) / 2;
        compareCount++;
        if (arr[mid] == target) {
            return mid;
        } else if (arr[mid] < target) {
            return binarySearch(arr, target, mid + 1, right);//右界
        } else {
            return binarySearch(arr, target, left, mid - 1);//左界
        }
    }
    
    //查找元素返回位置,否则返回接近该元素位置
    public static int binarySearch(int[] arr, int target) {
        int left = 0;
        int right = arr.length - 1;
        int index = -1;

        while (left <= right) {
            int mid = left + (right - left) / 2;

            if (arr[mid] == target) {
                index = mid;
                break;
            } else if (arr[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }

        // 如果目标元素不存在于数组中,则返回小于最接近该元素的位置
        if (index == -1) {
            index = right;
        }

        return index;
    }
    
    
    
    //三分搜索算法
    //使用一个 while 循环进行迭代,判断给定元素与数组中的中间元素进行比较
    //在每次比较时,我们都会通过增加 comparisons 数组的第一个元素的值来记录关键字比较的次数
    //如果找到匹配的元素,则返回 true 表示该元素出现在数组中
    //如果左边界 left 大于右边界 right,则跳出循环,并返回 false 表示该元素未出现在数组中
    public static boolean ternarySearch(int[] array, int target, int[] comparisons) {
        int left = 0;
        int right = array.length - 1;

        while (left <= right) {
            comparisons[0] += 2; // 每次循环会进行两次关键字比较
            int mid1 = left + (right - left) / 3;          //在1/3处
            int mid2 = right - (right - left) / 3;        //在2/3处

            if (array[mid1] == target) {
                return true; // 元素出现在数组中
            }
            if (array[mid2] == target) {
                return true; // 元素出现在数组中
            }

            if (target < array[mid1]) {          //在0-1/3范围内
                right = mid1 - 1;
            } else if (target > array[mid2]) { //在1/3-2/3范围内
                left = mid2 + 1;
            } else if (target < array[mid2]){   //在>2/3范围内
                right = mid2 - 1;
                left = mid1 + 1;
            }
        }

        return false; // 元素未出现在数组中
    }
    
    
    
    
    //找最大值的情况:
    //使用二分检索在先升后降(或先降后升)数组中找到一个满足数组中元素值严格大于两侧元素值的位置,即找到数组的峰值
    //返回数组中的峰值作为最大值
    //找最小值的情况:
    //使用二分检索在先升后降(或先降后升)数组中找到一个满足数组中元素值严格小于两侧元素值的位置
    //返回数组中的这个位置的元素作为最小值
    public static int findExtremeValue(int[] array, boolean findMax, int[] comparisons) {
        if (array == null || array.length == 0) {
            throw new IllegalArgumentException("数组不为空!");
        }

        int left = 0;
        int right = array.length - 1;

        while (left < right) {
            int mid = left + (right - left) / 2;
            comparisons[0]++; // 记录比较次数

            if (findMax) {//查找最大值true
                if (array[mid] < array[mid + 1]) {  
                    left = mid + 1; // 在右侧继续搜索
                } else {
                    right = mid; // 在左侧继续搜索
                }
            } else {//查找最小值false
                if (array[mid] > array[mid + 1]) {
                    left = mid + 1; // 在右侧继续搜索
                } else {
                    right = mid; // 在左侧继续搜索
                }
            }
        }

        return array[left]; // 左指针指向最小值或最大值
    }

}

UI.java

package com;



import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

	public class UI{
		
		 public static void main(String[] args) {  
		        SwingUtilities.invokeLater(() -> ViewUI());  
		    }  
	    

	    public static void ViewUI() {
	        // 创建用户界面
	        JFrame frame = new JFrame("UI界面");
	        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	        frame.setSize(300, 200);
	        frame.setLocation(500, 300);
	        frame.setLayout(new FlowLayout());
	        
	        JMenuBar menuBar = new JMenuBar();  
	        JMenu searchMenu = new JMenu("检索算法选择");  
	        
	        
	        JMenu sequentialSearch = new JMenu("顺序检索");
	        JMenu binarySearch = new JMenu("二分检索");
	        JMenu threeSearch = new JMenu("三分检索");       
	        JMenu shengchengArr = new JMenu("生成数组");
	       
	        JMenuItem renGong = new JMenuItem("人工生成数组");
	        JMenuItem ziDong = new JMenuItem("自动生成数组");
	        JMenuItem searchShu1 = new JMenuItem("搜素元素");
	        JMenuItem maxSearch = new JMenuItem("查找最大值");
	        JMenuItem minSearch = new JMenuItem("查找最小值");
	        JMenuItem searchShu2 = new JMenuItem("搜素元素");
	        JMenuItem searchShu3 = new JMenuItem("搜素元素");
	        
	        
	        //菜单项添加
	        sequentialSearch.add(searchShu1);
	        binarySearch.add(searchShu2);
	        binarySearch.add(maxSearch);
	        binarySearch.add(minSearch);
	        threeSearch.add(searchShu3);
	        shengchengArr.add(renGong);
	        shengchengArr.add(ziDong);
	        
	        
	        //菜单添加
	        searchMenu.add(shengchengArr);
	        searchMenu.add(sequentialSearch);
	        searchMenu.add(binarySearch);
	        searchMenu.add(threeSearch);
	       

	        
	        menuBar.add(searchMenu);
	        frame.setJMenuBar(menuBar);
	        
	        

	        renGong.addActionListener(new ActionListener() {
	            @Override
	            public void actionPerformed(ActionEvent e) {	                	                
	            	int[] arr = searchSuanfa.renGongArray();
	                
	                // 将数组转换为字符串
	                StringBuilder sb = new StringBuilder();
	                sb.append("生成的数组:");
	                for (int i = 0; i < arr.length; i++) {
	                    sb.append(arr[i]);
	                    if (i != arr.length - 1) {
	                        sb.append(", ");
	                    }
	                }
	                String arrString = sb.toString();
	                
	                JOptionPane.showMessageDialog(frame, arrString, "生成数组", JOptionPane.INFORMATION_MESSAGE);
	            }
	        });
	        


	        ziDong.addActionListener(new ActionListener() {
	            @Override
	            public void actionPerformed(ActionEvent e) {
	                int[] arr = searchSuanfa.generateArray();
	                
	                // 将数组转换为字符串
	                StringBuilder sb = new StringBuilder();
	                sb.append("生成的数组:");
	                for (int i = 0; i < arr.length; i++) {
	                    sb.append(arr[i]);
	                    if (i != arr.length - 1) {
	                        sb.append(", ");
	                    }
	                }
	                String arrString = sb.toString();
	                
	                JOptionPane.showMessageDialog(frame, arrString, "生成数组", JOptionPane.INFORMATION_MESSAGE);
	            }
	        });
	        
	        
	        searchShu1.addActionListener(new ActionListener() {
	            @Override
	            public void actionPerformed(ActionEvent e) {
	            	
	                int[] arr = searchSuanfa.ChooseGenerateArray();
	                
	                // 将数组转换为字符串
	                StringBuilder sb = new StringBuilder();
	                sb.append("生成的数组:");
	                for (int i = 0; i < arr.length; i++) {
	                    sb.append(arr[i]);
	                    if (i != arr.length - 1) {
	                        sb.append(", ");
	                    }
	                }
	                String arrString = sb.toString();
	                
	                JOptionPane.showMessageDialog(frame, arrString, "生成数组", JOptionPane.INFORMATION_MESSAGE);
	                
	                int catagory = searchSuanfa.checkArrayStatus(arr);
	                JOptionPane.showMessageDialog(frame, catagory,"显示数组状态(未排序0)、(升序1)、(降序2)、(先升后降3)、(先降后升4)", JOptionPane.INFORMATION_MESSAGE);
	                searchSuanfa.searchElement(arr,1);
	            }
	        });
	        
	        searchShu2.addActionListener(new ActionListener() {
	            @Override
	            public void actionPerformed(ActionEvent e) {
	                int[] arr = searchSuanfa.ChooseGenerateArray();
	                
	                // 将数组转换为字符串
	                StringBuilder sb = new StringBuilder();
	                sb.append("生成的数组:");
	                for (int i = 0; i < arr.length; i++) {
	                    sb.append(arr[i]);
	                    if (i != arr.length - 1) {
	                        sb.append(", ");
	                    }
	                }
	                String arrString = sb.toString();
	                
	                JOptionPane.showMessageDialog(frame, arrString, "生成数组", JOptionPane.INFORMATION_MESSAGE);
	                
	                int catagory = searchSuanfa.checkArrayStatus(arr);
	                JOptionPane.showMessageDialog(frame, catagory,"显示数组状态(未排序0)、(升序1)、(降序2)、(先升后降3)、(先降后升4)", JOptionPane.INFORMATION_MESSAGE);
	                searchSuanfa.searchElement(arr,2);//二分查找
	            }
	        });
	        
	        maxSearch.addActionListener(new ActionListener() {
	            @Override
	            public void actionPerformed(ActionEvent e) {
	                int[] arr = searchSuanfa.ChooseGenerateArray();
	                
	                // 将数组转换为字符串
	                StringBuilder sb = new StringBuilder();
	                sb.append("生成的数组:");
	                for (int i = 0; i < arr.length; i++) {
	                    sb.append(arr[i]);
	                    if (i != arr.length - 1) {
	                        sb.append(", ");
	                    }
	                }
	                String arrString = sb.toString();
	                
	                JOptionPane.showMessageDialog(frame, arrString, "生成数组", JOptionPane.INFORMATION_MESSAGE);
	                
	                int catagory = searchSuanfa.checkArrayStatus(arr);
	                JOptionPane.showMessageDialog(null, catagory,"显示数组状态(未排序0)、(升序1)、(降序2)、(先升后降3)、(先降后升4)", JOptionPane.INFORMATION_MESSAGE);
	                searchSuanfa.searchElement(arr,4);
	            }
	        });
	        
	        minSearch.addActionListener(new ActionListener() {
	            @Override
	            public void actionPerformed(ActionEvent e) {
	                int[] arr = searchSuanfa.ChooseGenerateArray();
	                
	                // 将数组转换为字符串
	                StringBuilder sb = new StringBuilder();
	                sb.append("生成的数组:");
	                for (int i = 0; i < arr.length; i++) {
	                    sb.append(arr[i]);
	                    if (i != arr.length - 1) {
	                        sb.append(", ");
	                    }
	                }
	                String arrString = sb.toString();
	                
	                JOptionPane.showMessageDialog(frame, arrString, "生成数组", JOptionPane.INFORMATION_MESSAGE);
	                
	                int catagory = searchSuanfa.checkArrayStatus(arr);
	                JOptionPane.showMessageDialog(null, catagory,"显示数组状态(未排序0)、(升序1)、(降序2)、(先升后降3)、(先降后升4)", JOptionPane.INFORMATION_MESSAGE);
	                searchSuanfa.searchElement(arr,5);
	            }
	        });
	   
	   
	        searchShu3.addActionListener(new ActionListener() {
	            @Override
	            public void actionPerformed(ActionEvent e) {
	                int[] arr = searchSuanfa.ChooseGenerateArray();
	                
	                // 将数组转换为字符串
	                StringBuilder sb = new StringBuilder();
	                sb.append("生成的数组:");
	                for (int i = 0; i < arr.length; i++) {
	                    sb.append(arr[i]);
	                    if (i != arr.length - 1) {
	                        sb.append(", ");
	                    }
	                }
	                String arrString = sb.toString();
	                
	                JOptionPane.showMessageDialog(frame, arrString, "生成数组", JOptionPane.INFORMATION_MESSAGE);
	                
	                int catagory = searchSuanfa.checkArrayStatus(arr);
	                JOptionPane.showMessageDialog(null, catagory,"显示数组状态(未排序0)、(升序1)、(降序2)、(先升后降3)、(先降后升4)", JOptionPane.INFORMATION_MESSAGE);
	                searchSuanfa.searchElement(arr,3);//三分查找
	            }
	        });
	        
	        
	        frame.setVisible(true);
	    }

	
	}


以上内容是我的实验作业,仅供参考, 有问题请自行查找解决。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值