15. 算法之排序算法

这篇具有很好参考价值的文章主要介绍了15. 算法之排序算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

排序是在软件开发中经常遇到的需求。比如基于订单的创建时间倒排,基于金额大小排序等等,那么这些排序底层是怎么写的呢,本节,我们就常用排序算法展开介绍。

1. 冒泡排序

1.1 算法思想

冒泡排序是最基础的排序算法。冒泡排序的英文是bubble sort,它是一种基础的交换排序。
冒泡排序这种排序算法的每一个元素都可以像小气泡一样,根据自身大小,一点一点地向着数组的一侧移动。
按照冒泡排序的思想,我们要把相邻的元素两两比较,当一个元素大于右侧相邻元素时,交换它们的位置;当一个元素小于或等于右侧相邻元素时,位置不变。

1.2 代码实现

package org.wanlong.sort;

/**
 * @author wanlong
 * @version 1.0
 * @description: 冒泡排序
 * @date 2023/6/6 13:38
 */
public class BubbleSort {

    public static int[] sort(int[] nums) {
        for (int i = 0; i < nums.length - 1; i++) {
            for (int j = 0; j < nums.length - 1; j++) {
                //临时变量 用于交换
                int tmp = 0;
                if (nums[j] > nums[j + 1]) {
                    tmp = nums[j];
                    nums[j] = nums[j + 1];
                    nums[j + 1] = tmp;
                }
            }
        }
        return nums;
    }
}

1.3 测试验证

@Test
public void testBubble(){
    int[] nums = new int[]{5, 8, 6, 3, 9, 2, 1, 7};
    for (int i : BubbleSort.sort(nums)) {
        System.out.println(i);
    }
}

运行结果:

1
2
3
5
6
7
8
9

1.4 冒泡排序优化

1.4.1 优化项

  1. 已经循环过的不需要再遍历,每次外层循环会将一个元素移动到最左边或者最右边,为此,内层循环遍历的时候不需要每次都遍历整个数组
  2. 在外层循环处,设置标志isSort,默认为排好,如果不交换则跳出本次循环,说明所有元素有序,可以不继续了

1.4.2 代码实现

/**
* @Description: 排序优化
* @Author: wanlong
* @Date: 2023/6/6 13:51
* @param nums:
* @return int[]
**/
public static int[] sort2(int[] nums) {
   //是否已排序标识
   boolean isSort=true;
   for (int i = 0; i < nums.length - 1; i++) {
       //优化1,每次循环迭代会将最大的元素移动到末尾,所以内存循环不需要移动到末尾元素
       for (int j = 0; j < nums.length - 1-i; j++) {
           //临时变量 用于交换
           int tmp = 0;
           if (nums[j] > nums[j + 1]) {
               //有交换说明还没排好序,标识设置为false
               isSort=false;
               tmp = nums[j];
               nums[j] = nums[j + 1];
               nums[j + 1] = tmp;
           }
       }
       //排好了跳出循环
       if (isSort){
           break;
       }
   }
   return nums;
}

1.4.3 测试验证

@Test
public void testBubble2(){
    int[] nums = new int[]{5, 8, 6, 3, 9, 2, 1, 7};
    for (int i : BubbleSort.sort2(nums)) {
        System.out.println(i);
    }
}

运行结果:

1
2
3
5
6
7
8
9

2. 快速排序

2.1 算法思想

2.1.1 简介

同冒泡排序一样,快速排序也属于交换排序,通过元素之间的比较和交换位置来达到排序的目的。
不同的是,冒泡排序在每一轮中只把1个元素冒泡到数列的一端,而快速排序则在每一轮挑选一个基准元素,并让其他比它大的元素移动到数列一边,比它小的元素移动到数列的另一边,从而把数列拆解成两个部分,这种思路就叫作分治法
15. 算法之排序算法

2.1.2 基准元素选择

基准元素,英文是pivot,在分治过程中,以基准元素为中心,把其他元素移动到它的左右两边。
我们可以随机选择一个元素作为基准元素,并且让基准元素和数列首元素交换位置。
15. 算法之排序算法

2.1.3 元素的交换

选定了基准元素以后,我们要做的就是把其他元素中小于基准元素的都交换到基准元素一边,大于基准元素的都交换到基准元素另一边。

2.1.3.1 双边循环法
  1. 选定基准元素pivot,并且设置两个指针left和right,指向数列的最左和最右两个元素
    15. 算法之排序算法

  2. 接下来进行第1次循环:从right指针开始,让指针所指向的元素和基准元素做比较。如果大于或等于pivot,则指针向左移动;如果小于pivot,则right指针停止移动,切换到left指针轮到left指针行动,让指针所指向的元素和基准元素做比较。如果小于或等于pivot,则指针向右移动;

  3. 如果大于pivot,则left指针停止移动左右指针指向的元素交换位置,由于left开始指向的是基准元素,判断肯定相等,所以left右移1位
    15. 算法之排序算法

  4. 由于7>4,left指针在元素7的位置停下。这时,让left和right指针所指向的元素进行交换。
    15. 算法之排序算法

  5. 进入第2次循环,重新切换到right指针,向左移动。right指针先移,动到8,8>4,继续左移。由于2<4,停止在2的位置

15. 算法之排序算法

2.1.3.2 单边循环法

单边循环法只从数组的一边对元素进行遍历和交换。
开始和双边循环法相似,首先选定基准元素pivot。同时,设置一个mark指针指向数列起始位置,
这个mark指针代表小于基准元素的区域边界。
15. 算法之排序算法
接下来,从基准元素的下一个位置开始遍历数组。
如果遍历到的元素大于基准元素,就继续往后遍历
如果遍历到的元素小于基准元素,则需要做两件事:
第一,把mark指针右移1位,因为小于pivot的区域边界增大了1;
第二,让最新遍历到的元素和mark指针所在位置的元素交换位置,因为最新遍历的元素归属于小
于pivot的区域

  1. 遍历到元素7,7>4,所以继续遍历。
    15. 算法之排序算法
  2. 遍历到的元素是3,3<4,所以mark指针右移1位
    15. 算法之排序算法
  3. 让元素3和mark指针所在位置的元素交换,因为元素3归属于小于pivot的区域。
    15. 算法之排序算法
  4. 按照这个思路,继续遍历,后续步骤如图所示
    15. 算法之排序算法

2.2 代码实现

2.2.1 双边循环

package org.wanlong.sort;

/**
 * @author wanlong
 * @version 1.0
 * @description: 快速排序
 * @date 2023/6/7 18:39
 */
public class QuickSort {

    public static void quickSort(int[] arr, int startIndex, int endIndex){
        // 递归结束条件:startIndex大于或等于endIndex时
        if (startIndex >= endIndex) {
            return;
        }
        // 得到基准元素位置
        int pivotIndex = partition(arr, startIndex, endIndex);
        // 根据基准元素,分成两部分进行递归排序
        quickSort(arr, startIndex, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, endIndex);
    }



    /**
     * 分治(双边循环法)
     *
     * @param arr        待交换的数组
     * @param startIndex 起始下标
     * @param endIndex   结束下标
     * @return
     */
    private static int partition(int[] arr, int startIndex, int endIndex) {
        // 取第1个位置(也可以选择随机位置)的元素作为基准元素
        int pivot = arr[startIndex];
        int left = startIndex;
        int right = endIndex;
        while (left != right) {
            //控制right 指针比较并左移
            while (left < right && arr[right] > pivot) {
                right--;
            }
            //控制left指针比较并右移
            while (left < right && arr[left] <= pivot) {
                left++;
            }
            //交换left和right 指针所指向的元素
            if (left < right) {
                int p = arr[left];
                arr[left] = arr[right];
                arr[right] = p;
            }
        }
        //pivot 和指针重合点交换
        arr[startIndex] = arr[left];
        arr[left] = pivot;
        return left;
    }
}

2.2.2 单边循环

public class QuickSort {
    public static void quickSort2(int[] arr, int startIndex,
                                 int endIndex) {
        // 递归结束条件:startIndex大于或等于endIndex时
        if (startIndex >= endIndex) {
            return;
        }
        // 得到基准元素位置
        int pivotIndex = partition2(arr, startIndex, endIndex);
        // 根据基准元素,分成两部分进行递归排序
        quickSort2(arr, startIndex, pivotIndex - 1);
        quickSort2(arr, pivotIndex + 1, endIndex);
    }


    /**
     * 分治(单边循环法)
     *
     * @param arr 待交换的数组
     * @param startIndex 起始下标
     * @param endIndex 结束下标
     * @return
     */
    private static int partition2(int[] arr, int startIndex, int endIndex) {
        // 取第1个位置(也可以选择随机位置)的元素作为基准元素
        int pivot = arr[startIndex];
        int mark = startIndex;
        for (int i = startIndex + 1; i <= endIndex; i++) {
            if (arr[i] < pivot) {
                mark++;
                int p = arr[mark];
                arr[mark] = arr[i];
                arr[i] = p;
            }
        }
        arr[startIndex] = arr[mark];
        arr[mark] = pivot;
        return mark;
    }
}

2.3 测试验证

    @Test
    public void testQuickSingle(){
        int[] nums = new int[]{5, 8, 6, 3, 9, 2, 1, 7};
        QuickSort.quickSort2(nums,0,nums.length-1);
        for (int i : nums) {
            System.out.println(i);
        }
    }

    @Test
    public void testQuickDouble(){
        int[] nums = new int[]{5, 8, 6, 3, 9, 2, 1, 7};
        QuickSort.quickSort(nums,0,nums.length-1);
        for (int i : nums) {
            System.out.println(i);
        }
    }

运行结果和预期一致:

1
2
3
5
6
7
8
9

3. 堆排序

3.1 算法思想

堆排序:堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。
大顶堆:每个结点的值都大于或等于其左右孩子结点的值
小顶堆:每个结点的值都小于或等于其左右孩子结点的值

之前介绍过,因为堆是完全二叉树,那么我们完全可以用数组来维护堆这种数据结构
我们用简单的公式来描述一下堆的定义就是:
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] 2*(i+1)
小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。

  1. 构造初始堆,将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。

15. 算法之排序算法

  1. 此时我们从最后一个非叶子结点开始(叶结点自然不用调整,第一个非叶子结点 arr.length/2-
    1=5/2-1=1,也就是下面的6结点),从左至右,从下至上进行调整
    15. 算法之排序算法
  2. 找到第二个非叶节点4,由于[4,9,8]中9元素最大,4和9交换
    15. 算法之排序算法
  3. 这时,交换导致了子根[4,5,6]结构混乱,继续调整,[4,5,6]中6最大,交换4和6。
    15. 算法之排序算法
  4. 我们就将一个无需序列构造成了一个大顶堆。将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换
    将堆顶元素9和末尾元素4进行交换

15. 算法之排序算法

  1. 重新调整结构,使其继续满足堆定义
    15. 算法之排序算法
  2. 再将堆顶元素8与末尾元素5进行交换,得到第二大元素8
    15. 算法之排序算法
  3. 后续过程,继续进行调整,交换,如此反复进行,最终使得整个序列有序

3.2 代码实现

package org.wanlong.sort;

/**
 * @author wanlong
 * @version 1.0
 * @description: 堆排序
 * @date 2023/6/7 18:59
 */
public class HeapSort {

    public static void sort(int[] array) {
        // 1. 把无序数组构建成最大堆
        for (int i = array.length / 2 - 1; i >= 0; i--) {
            adjustHeap(array, i, array.length);
        }
        // 2. 调整堆结构+交换堆顶元素与末尾元素,调整堆产生新的堆顶
        for (int i = array.length - 1; i > 0; i--) {
            // 最后1个元素和第1个元素进行交换
            int temp = array[i];
            array[i] = array[0];
            array[0] = temp;
            // “下沉”调整最大堆
            adjustHeap(array, 0, i);
        }
    }

    public static void adjustHeap(int[] array, int parentIndex, int length) {
        // temp 保存父节点值,用于最后的赋值
        int temp = array[parentIndex];
        int childIndex = 2 * parentIndex + 1;
        while (childIndex < length) {
            // 如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子
            if (childIndex + 1 < length && array[childIndex + 1] >
                    array[childIndex]) {
                childIndex++;
            }
            // 如果父节点大于任何一个孩子的值,则直接跳出
            if (temp >= array[childIndex])
                break;
            //无须真正交换,单向赋值即可
            array[parentIndex] = array[childIndex];
            parentIndex = childIndex;
            //下一个左孩子
            childIndex = 2 * childIndex + 1;
        }
        array[parentIndex] = temp;
    }
}

3.3 测试验证

@Test
public void testHeapSort(){
    int[] nums = new int[]{5, 8, 6, 3, 9, 2, 1, 7};
    HeapSort.sort(nums);
    for (int i : nums) {
        System.out.println(i);
    }
}

4. 计数排序

4.1 算法思想

计数排序,这种排序算法是利用数组下标来确定元素的正确位置的。

假设数组中有10个整数,取值范围为0~10,要求用最快的速度把这10个整数从小到大进行排序。
可以根据这有限的范围,建立一个长度为11的数组。数组下标从0到10,元素初始值全为0
假设数组数据为:9,1,2,7,8,1,3,6,5,3
下面就开始遍历这个无序的随机数列,每一个整数按照其值对号入座,同时,对应数组下标的元素进行加1操作
例如第1个整数是9,那么数组下标为9的元素加1
15. 算法之排序算法
当数列遍历完毕时,数组的状态如下:
15. 算法之排序算法
该数组中每一个下标位置的值代表数列中对应整数出现的次数,直接遍历数组,输出数组元素的下标值,元素的值是几,就输出几次,0不输出
则顺序输出是:1、1、2、3、3、5、6、7、8、9

可以看到,计数排序适合于连续的取值范围不大的数组不连续和取值范围过大会造成数组过大
如果起始数不是从0开始,比如分数排序
95,94,91,98,99,90,99,93,91,92
数组起始数为90,这样数组前面的位置就浪费了
可以采用偏移量的方式:
15. 算法之排序算法

4.2 代码实现

package org.wanlong.sort;

/**
 * @author wanlong
 * @version 1.0
 * @description: 计数排序
 * @date 2023/6/5 19:00
 */
public class CountSort {

    public static int[] countSort(int[] array, int offset) {
        int[] nums = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            int n = (array[i] - offset);
            //数字自增
            nums[n]++;
        }
        int[] nums2 = new int[array.length];
        // i是计数数组下标,k是新数组下标
        for (int i = 0, k = 0; i < nums.length; i++) {
            for (int j = 0; j < nums[i]; j++) {
                nums2[k++] = i + offset;
            }
        }
        return nums2;
    }
}

4.3 测试验证

@Test
public void testCountSort(){
    int[] nums = new int[]{95, 94, 91, 98, 99, 90, 99, 93, 91, 92};
    for (int i : CountSort.countSort(nums,90)) {
        System.out.println(i);
    }
}

5. 桶排序

5.1 算法思想

桶排序同样是一种线性时间的排序算法。桶排序需要创建若干个桶来协助排序。

每一个桶(bucket)代表一个区间范围,里面可以承载一个或多个元素。

  1. 桶排序的第1步,就是创建这些桶,并确定每一个桶的区间范围具体需要建立多少个桶,如何确定桶的区间范围,有很多种不同的方式。

  2. 我们这里创建的桶数量等于原始数列的元素数量,除最后一个桶只包含数列最大值外, 前面各个桶的区间按照比例来确定。
    区间跨度 = (最大值-最小值)/ (桶的数量 - 1)

  3. 假设有一个非整数数列如下:
    4.5,0.84,3.25,2.18,0.5
    15. 算法之排序算法

  4. 遍历原始数列,把元素对号入座放入各个桶中。
    15. 算法之排序算法

  5. 对每个桶内部的元素分别进行排序(显然,只有第1个桶需要排序)
    15. 算法之排序算法

  6. 遍历所有的桶,输出所有元素

5.2 代码验证

package org.wanlong.sort;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;

/**
 * @author wanlong
 * @version 1.0
 * @description:
 * @date 2023/6/3 19:01
 */
public class BucketSort {

    public static double[] bucketSort(double[] array) {
        double max = 0;
        double min = 0;
        //获得最大值和最小值之间的差
        for (int i = 0; i < array.length; i++) {
            if (array[i] > max) {
                max = array[i];
            }
            if (array[i] < min) {
                min = array[i];
            }
        }
        double d = max - min;
        //桶初始化
        int bucketNum = array.length;
        ArrayList<LinkedList<Double>> bucketList =
                new ArrayList<LinkedList<Double>>(bucketNum);
        for (int i = 0; i < bucketNum; i++) {
            bucketList.add(new LinkedList<Double>());
        }
        //将每个元素放入桶中
        for (int i = 0; i < array.length; i++) {
            int num = (int) ((array[i] - min) * (bucketNum - 1) / d);
            bucketList.get(num).add(array[i]);
        }
        //对每个桶内部进行排序
        for (int i = 0; i < bucketList.size(); i++) {
            Collections.sort(bucketList.get(i));
        }
        //输出全部元素
        double[] sortedArray = new double[array.length];
        int index = 0;
        for (LinkedList<Double> list : bucketList) {
            for (double element : list) {
                sortedArray[index] = element;
                index++;
            }
        }
        return sortedArray;
    }
}

5.3 测试验证

@Test
public void testBucketSort(){
    double[] nums = {4.12, 6.421, 0.0023, 3.0, 2.123, 8.122, 4.12, 10.09};
    for (double i : BucketSort.bucketSort(nums)) {
        System.out.println(i);
    }
}

6. 总结

6.1 稳定性概念介绍

如果大小相同的两个值在排序之前和排序之后的先后顺序不变,那就可以说这种排序算法是稳定的。
比如初始序列为 1,2,2,3,4
排序后序列:1,2,2,3,4
并且序列中两个2的元素顺序没有调整,则算法可认为是稳定的。反之,则算法是不稳定的

6.2 几种排序算法比较

15. 算法之排序算法

6.3 适用场景

严格来说,算法的优劣不是绝对的,算法的性能取决于数据的大小,数据顺序是否已基本有序,存储空间限制等。下面列出来的是一些网上的经验总结,但是我们实际开发中,需要基于实际情况,来决定使用哪种排序算法文章来源地址https://www.toymoban.com/news/detail-474809.html

  1. 当数据规模较大时,应用速度最快的排序算法,可以考虑使用快速排序。当记录随机分布的时候,快速排序平均时间最短,但是会出现最坏的情况,这个时候的时间复杂度是O(n^2),且递归深度为n,所需的占空间为O(n)
  2. 堆排序不会出现快排那样最坏情况,且堆排序所需的辅助空间比快排要少,但是这两种算法都不是稳定的,要求排序时是稳定的,可以考虑用归并排序。
  3. 特殊的桶排序、基数排序都是稳定且高效的排序算法,但有一定的局限性:
    1、关键字可分解。
    2、记录的关键字位数较少,如果密集更好
    3、如果是数字时,最好是无符号的,否则将增加相应的映射复杂度,可先将其正负分开排序。
  4. 当文件的初态已经基本有序,可以用优化后的冒泡排序。

到了这里,关于15. 算法之排序算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 易语言软件定制软件开发脚本开发协议软件电脑网站APP应用视频制作工程制作

    随着信息技术的不断发展,易语言软件定制开发已成为许多公司的一项重要业务。本文将探讨如何利用易语言承接软件定制软件开发脚本开发协议软件电脑网站APP应用视频制作工程制作。 一、易语言概述 易语言是一种简单易学的编程语言,它采用中文编程,让不会英文的初

    2024年02月08日
    浏览(77)
  • 用python开发软件的步骤,如何用python做软件开发

    大家好,小编来为大家解答以下问题,如何用python做软件开发,用python开发软件的步骤,今天让我们一起来看看吧!   参与文末每日话题讨论,赠送异步新书 异步图书君 学习目标 知道有序的软件开发过程的步骤。 了解遵循输入、处理、输出(IPO)模式的程序,并能够以简单

    2024年02月06日
    浏览(75)
  • 数据驱动开发模式将软件开发过程改造成一个公式化的迭代模式,可以提升软件开发效率,缩短开发周期,降低开发成本。

    作者:禅与计算机程序设计艺术 随着云计算、大数据等新兴技术的应用,软件开发领域迎来了蓬勃发展的时期。各种编程语言、框架、工具不断涌现,协同工作的强烈需求已经成为当今社会的一个主要挑战。这就需要一种新的开发方式来适应这种复杂多变的环境。传统的瀑布

    2024年02月06日
    浏览(76)
  • 中文编程开发语言工具开发的实际软件案例:称重管理系统软件

    中文编程开发语言工具开发的实际软件案例:称重管理系统软件 中文编程开发语言工具开发的实际软件案例:称重管理系统软件,软件可以安装在电脑上,也可以安装在收银机上,支持触摸和鼠标点,想学编程可以关注系统化的编程课程。 中文编程系统化教程,不需英语基

    2024年02月07日
    浏览(78)
  • 易语言软件定制开发爬虫模拟协议填写自动化办公软件开发多人团队

    在当今快速发展的信息化时代,企业对于高效、自动化的软件需求日益增长。而易语言软件定制开发爬虫模拟协议填写自动化办公软件开发多人团队,正是为了满足这一需求而诞生的。 一、团队背景 技术顾问、维:Daxiami6789 易语言软件定制开发爬虫模拟协议填写自动化办公

    2024年02月05日
    浏览(67)
  • 开源软件:推动软件开发行业繁荣的关键力量

    在数字化时代,软件开发行业的发展日新月异,开源软件作为一种推动力,正逐渐改变着软件开发的生态。本文将探讨开源软件如何成为推动软件开发行业繁荣的力量,并分析其对我国软件产业的发展意义。 开源软件,是指源代码公开、可以自由使用和修改的软件。这种软件

    2024年02月22日
    浏览(77)
  • 软件架构设计(八) 基于架构的软件开发方法

    ABSD虽然在日常生活中并不常见,但是在考试中却是极为常见的,因此仍然是我们的重点学习知识点。 特点 基于架构的软件设计(Architecture-Based Software Design,ABSD),这个开发方法是 架构驱动 。 即 强调由业务、质量和功能需求的组合驱动架构设计 。就是会考虑到业务的情况

    2024年02月09日
    浏览(47)
  • 大数据开发和软件开发哪个前景好?

    大数据开发和软件开发哪个前景好?大数据开发学习有难度,零基础入门要先学习Java语言打基础,然后进入大数据技术体系的学习,学习Hadoop、Spark、Storm等知识。软件开发工程师根据不同的学科从事的岗位也千差万别。 先说说大数据开发岗位和就业的前景,大数据开发岗位

    2024年02月06日
    浏览(44)
  • 开发复杂软件的系统方法(二)之软件建模

    这几周与公司的软件开发专家(职称)讨论产品的软件新架构与方案,主要涉及两点 是否复用现有的核心机制 基于领域建模设计 关于第一点,双方达成一致。 关于第二点,领域可以理解为业务,业务专家(产品经理,需求工程师,临床工程师等)与研发人员一起,通过头脑风暴

    2024年02月02日
    浏览(54)
  • 软件外包开发的VUE开发框架

    Vue.js(通常简称为Vue)是一个流行的渐进式JavaScript框架,用于构建用户界面。它的核心库专注于视图层,但也可以结合其他库和工具来构建完整的单页面应用(SPA)。以下分享Vue.js的开发框架和特点,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公

    2024年02月13日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包