别再忽视数组排序的重要性了

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

  在日常开发中,数组排序是一个非常常见的操作。很多开发者可能会认为排序只是一个简单的操作,但实际上,实现一个高效、稳定、可扩展的排序算法并不容易。因此,在本文中,我想探讨一下为什么数组排序如此重要,以及如何在Java中实现各种排序算法。

摘要

  数组排序是一种非常基础的算法,但却在日常开发中经常被忽视。本文将介绍Java中常用的排序算法,包括冒泡排序、插入排序、选择排序、快速排序、归并排序和堆排序。我们将通过代码解析、应用场景案例、优缺点分析、类代码方法介绍和测试用例来帮助读者更好地理解这些算法。

正文

简介

  排序是将一组元素按照某种规律排列的过程。通常情况下,排序是将一组无序的元素按照从小到大或从大到小的顺序排列。在Java中,我们可以使用Arrays.sort()方法来对数组进行排序。但是,这种排序方法在处理大规模数据时可能会出现运行时间过长的情况。因此,在某些情况下,我们需要使用更高效的排序算法来提高程序的性能。

源代码解析

冒泡排序

  冒泡排序是一种简单的排序算法。它通过反复交换相邻的元素来对数组进行排序。该算法的时间复杂度为O(n^2)。

public static void bubbleSort(int[] arr) {int len = arr.length;for (int i = 0; i < len-1; i++) {for (int j = 0; j < len-i-1; j++) {if (arr[j] > arr[j+1]) {int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}
}

代码分析:

  这是一个经典的冒泡排序算法,其主要思想是将相邻的数进行比较,如果顺序不对则进行交换,一次遍历后可以将一个最大或最小的数移到数组的末尾或开头,然后再进行下一次遍历。重复这个过程,直到排序完整个数组。

该算法的时间复杂度为O(n^2),并不适用于大规模数据的排序。因此,在实际应用中,如果需要对大量数据进行排序,应该使用更高效的排序算法,例如归并排序、快速排序等。

插入排序

  插入排序是一种简单的排序算法。它通过将未排序的元素插入已排序的序列中来对数组进行排序。该算法的时间复杂度为O(n^2)。

public static void insertionSort(int[] arr) {int len = arr.length;for (int i = 1; i < len; i++) {int key = arr[i];int j = i - 1;while (j >= 0 && arr[j] > key) {arr[j+1] = arr[j];j--;}arr[j+1] = key;}
}

代码分析:

  上述代码实现了插入排序算法。插入排序算法的基本思想是将待排序序列分为已排序区间和未排序区间,每次从未排序区间中选择一个元素,将其插入已排序区间中的正确位置,直到未排序区间为空。代码实现中,for循环遍历未排序序列,将i位置的元素作为key,将key插入到已排序区间的正确位置,即将key与已排序区间中的元素从后往前进行比较,将比key大的元素往后移动一位。当已排序区间中找到一个比key小的元素时,将key插入到该元素后面即可。时间复杂度为O(n^2)。

选择排序

  选择排序是一种简单的排序算法。它通过选择未排序元素中的最小值来对数组进行排序。该算法的时间复杂度为O(n^2)。

public static void selectionSort(int[] arr) {int len = arr.length;for (int i = 0; i < len-1; i++) {int minIndex = i;for (int j = i+1; j < len; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}
}

代码分析:

  这段代码是实现选择排序的算法。选择排序的思想是每次从未排序的数组中选择最小的元素,放到已排序的数组末尾,直到所有元素都被排序。具体实现如下:

  1. 对于未排序部分的数组,找到其中最小的元素。
  2. 将最小的元素与未排序部分的第一个元素交换位置。
  3. 从剩余未排序部分的数组中找到最小的元素,将其与未排序部分的第二个元素交换位置。
  4. 依次类推,直到未排序部分为空。

代码中,外层循环用于控制已排序部分的末尾,内层循环用于查找未排序部分中的最小元素,并与已排序部分的末尾交换位置。时间复杂度为O(n^2)。

需要注意的是,这段代码没有处理异常情况,例如传入空数组。在实际应用中,需要进行相应的异常处理。

快速排序

  快速排序是一种高效的排序算法。它通过选定一个基准值,将数组分为两个子数组,然后递归地对子数组进行排序。该算法的时间复杂度为O(nlogn)。

public static void quickSort(int[] arr, int low, int high) {if (low < high) {int pi = partition(arr, low, high);quickSort(arr, low, pi-1);quickSort(arr, pi+1, high);}
}public static int partition(int[] arr, int low, int high) {int pivot = arr[high];int i = low - 1;for (int j = low; j < high; j++) {if (arr[j] < pivot) {i++;int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}int temp = arr[i+1];arr[i+1] = arr[high];arr[high] = temp;return i+1;
}

代码分析:

  这是一个使用快速排序算法实现的代码。

函数quickSort(int[] arr, int low, int high)用于对一个给定的数组arr中的元素进行排序。low和high分别表示数组的起始和结束位置。如果low小于high,那么函数会选取数组中的一个元素作为基准值(pivot),并将数组中小于基准值的元素放到基准值的左边,大于基准值的元素放到右边。然后,递归调用quickSort函数对左侧和右侧的子数组进行排序。

函数partition(int[] arr, int low, int high)用于选取基准值(pivot),并将小于基准值的元素放到基准值的左边,大于基准值的元素放到右边。具体地,它首先选取数组中的最后一个元素作为基准值(pivot),然后遍历数组中low到high-1位置的元素。如果某个元素小于基准值,那么就将i位置的元素(i为小于基准值的元素的最后一个位置)和这个元素进行交换,表示这个元素应该放到基准值的左边。最后,将i+1位置的元素(也就是大于基准值的元素的第一个位置)和基准值进行交换,表示基准值被放到了正确的位置。

整个算法的核心是partition函数,它用于将数组中的元素划分成小于基准值和大于基准值的两部分。在每次对一个子数组进行排序时,我们都需要选取一个新的基准值,并用partition函数来对子数组进行划分。最终,整个数组就会被排好序。

归并排序

  归并排序是一种高效的排序算法。它通过将数组分为两个子数组,然后递归地对子数组进行排序,最后将两个已排序的子数组合并成一个有序的数组。该算法的时间复杂度为O(nlogn)。

public static void mergeSort(int[] arr, int low, int high) {if (low < high) {int mid = (low + high) / 2;mergeSort(arr, low, mid);mergeSort(arr, mid+1, high);merge(arr, low, mid, high);}
}public static void merge(int[] arr, int low, int mid, int high) {int[] temp = new int[high-low+1];int i = low, j = mid+1, k = 0;while (i <= mid && j <= high) {if (arr[i] < arr[j]) {temp[k++] = arr[i++];} else {temp[k++] = arr[j++];}}while (i <= mid) {temp[k++] = arr[i++];}while (j <= high) {temp[k++] = arr[j++];}for (int m = 0; m < temp.length; m++) {arr[low+m] = temp[m];}
}

代码分析:

  这段代码实现了归并排序算法。归并排序是一种分治算法,它将待排序的数组分成两个子数组,分别对它们进行排序,然后将两个已排序的子数组合并成一个有序的数组。该算法的时间复杂度为O(nlogn)。

该算法分为两个函数,mergeSort和merge。

mergeSort函数接收三个参数:待排序的数组,数组的起始下标(low),数组的结束下标(high)。它使用递归的方式将数组一分为二,然后对两个子数组分别调用自身进行排序,最后将两个已排序的子数组合并成一个有序的数组。如果low小于high,则进行排序,否则直接返回。

merge函数接收四个参数:待排序的数组,数组的起始下标(low),数组的中间下标(mid),数组的结束下标(high)。它的作用是将两个已排序的子数组合并成一个有序的数组。它创建一个临时数组temp,用i、j、k三个指针变量来遍历两个已排序的子数组,将它们中较小的元素放入temp数组中,最后再将temp数组中的元素复制回原数组中。

最终,当mergeSort函数执行完毕后,原数组就会被排序成一个有序数组。

堆排序

  堆排序是一种高效的排序算法。它通过将数组看作一棵完全二叉树,然后将数组转换为最大堆或最小堆,最后将堆排序,得到一个有序的数组。该算法的时间复杂度为O(nlogn)。

public static void heapSort(int[] arr) {int len = arr.length;for (int i = len/2-1; i >= 0; i--) {heapify(arr, len, i);}for (int i = len-1; i >= 0; i--) {int temp = arr[0];arr[0] = arr[i];arr[i] = temp;heapify(arr, i, 0);}
}public static void heapify(int[] arr, int n, int i) {int largest = i;int l = 2*i + 1;int r = 2*i + 2;if (l < n && arr[l] > arr[largest]) {largest = l;}if (r < n && arr[r] > arr[largest]) {largest = r;}if (largest != i) {int temp = arr[i];arr[i] = arr[largest];arr[largest] = temp;heapify(arr, n, largest);}
}

代码分析:

  这是一个堆排序的Java实现。

  堆排序的基本思想是:首先将待排序的数组构造成一个大顶堆,然后将堆顶元素与堆底元素交换并下调,使得剩余元素重新构成一个大顶堆,重复此步骤直到堆排序完成。

  这个Java代码中,heapSort()方法遍历数组并调用heapify()方法,将数组构造成一个大顶堆。然后,它对数组进行排序,直到排序完成。

  heapify()方法用来调整堆,确保以i为根节点的子树满足大顶堆的性质。它会检查左右子节点的值,找到其中最大值,如果最大值不是当前节点值,那么就交换它和最大值,然后递归调用heapify(),直到整个堆满足大顶堆的性质。

应用场景案例

  在日常开发中,排序算法的应用非常广泛。下面是一些排序算法的应用场景:

  • 冒泡排序:适用于小规模数据的排序。
  • 插入排序:适用于对于大部分数据已经有序的情况下的排序。
  • 选择排序:适用于需要排序的数据规模较小的情况。
  • 快速排序:适用于需要高效地排序大规模数据的情况。
  • 归并排序:适用于需要高效地排序大规模数据的情况。
  • 堆排序:适用于需要高效地排序大规模数据的情况。

优缺点分析

不同的排序算法各有优缺点,下面是一些排序算法的优缺点:

  • 冒泡排序:简单易懂,代码实现简单,但是时间复杂度较高,不适用于大规模数据的排序。

  • 插入排序:代码简单,对于大部分数据已经有序的情况下排序效率较高,但是对于逆序排列的数据,时间复杂度较高。

  • 选择排序:简单易懂,代码实现简单,适用于需要排序的数据规模较小的情况,但是时间复杂度较高,不适用于大规模数据的排序。

  • 快速排序:时间复杂度较低,适用于需要高效地排序大规模数据的情况,但是可能会受到递归深度的影响,导致栈溢出。

  • 归并排序:时间复杂度较低,适用于需要高效地排序大规模数据的情况,但是需要额外的存储空间,可能会导致空间浪费。

  • 堆排序:时间复杂度较低,适用于需要高效地排序大规模数据的情况,但是需要额外的存储空间,不适用于非连续的数据结构。

因此,在选择排序算法时,需要根据实际情况来选择最适合的排序算法。

类代码方法介绍

  • bubbleSort(int[] arr):实现冒泡排序算法,将给定的数组按从小到大的顺序排序。
  • insertionSort(int[] arr):实现插入排序算法,将给定的数组按从小到大的顺序排序。
  • selectionSort(int[] arr):实现选择排序算法,将给定的数组按从小到大的顺序排序。
  • quickSort(int[] arr, int low, int high):实现快速排序算法(递归实现),将给定的数组按从小到大的顺序排序。
  • partition(int[] arr, int low, int high):快速排序算法中的划分函数,用于将数组分为两个子数组。
  • mergeSort(int[] arr, int low, int high):实现归并排序算法(递归实现),将给定的数组按从小到大的顺序排序。
  • merge(int[] arr, int low, int mid, int high):归并排序算法中的合并函数,用于合并两个已排序的子数组。
  • heapSort(int[] arr):实现堆排序算法,将给定的数组按从小到大的顺序排序。
  • heapify(int[] arr, int n, int i):堆排序算法中的堆化函数,用于将数组转换为最大堆或最小堆。

测试用例

  为了验证数组排序算法的正确性和效率,我们需要编写一些相应的测试用例。以下是对排序算法进行测试的示例代码:

测试代码演示

package com.example.javase.se.sort;import java.util.Arrays;/**a* @Author ms* @Date 2023-11-14 21:11*/
public class SortTest {public static void main(String[] args) {int[] arr = {9, 3, 1, 4, 6, 8, 7, 5, 2};int[] expected = {1, 2, 3, 4, 5, 6, 7, 8, 9};SortingUtils.bubbleSort(arr);System.out.println("Bubble Sort: " + Arrays.toString(arr));if (Arrays.equals(expected, arr))System.out.println("Bubble Sort passed\n");elseSystem.out.println("Bubble Sort failed\n");arr = new int[]{9, 3, 1, 4, 6, 8, 7, 5, 2};SortingUtils.insertionSort(arr);System.out.println("Insertion Sort: " + Arrays.toString(arr));if (Arrays.equals(expected, arr))System.out.println("Insertion Sort passed\n");elseSystem.out.println("Insertion Sort failed\n");arr = new int[]{9, 3, 1, 4, 6, 8, 7, 5, 2};SortingUtils.selectionSort(arr);System.out.println("Selection Sort: " + Arrays.toString(arr));if (Arrays.equals(expected, arr))System.out.println("Selection Sort passed\n");elseSystem.out.println("Selection Sort failed\n");arr = new int[]{9, 3, 1, 4, 6, 8, 7, 5, 2};SortingUtils.quickSort(arr, 0, arr.length - 1);System.out.println("Quick Sort: " + Arrays.toString(arr));if (Arrays.equals(expected, arr))System.out.println("Quick Sort passed\n");elseSystem.out.println("Quick Sort failed\n");arr = new int[]{9, 3, 1, 4, 6, 8, 7, 5, 2};SortingUtils.mergeSort(arr, 0, arr.length - 1);System.out.println("Merge Sort: " + Arrays.toString(arr));if (Arrays.equals(expected, arr))System.out.println("Merge Sort passed\n");elseSystem.out.println("Merge Sort failed\n");arr = new int[]{9, 3, 1, 4, 6, 8, 7, 5, 2};SortingUtils.heapSort(arr);System.out.println("Heap Sort: " + Arrays.toString(arr));if (Arrays.equals(expected, arr))System.out.println("Heap Sort passed\n");elseSystem.out.println("Heap Sort failed\n");}
}

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

  以上示例代码中,使用JUnit框架编写了针对数组排序算法的单元测试用例,确保排序算法的正确性和效率。

  这段代码是一个用于测试排序算法的程序。其中包含了不同种类的排序算法,如冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序。程序会将一个包含9个元素的整型数组传入这些排序算法中进行排序,并输出排序后的结果。在排序完成后,程序会将排序后的结果与一个期望的有序数组进行比较,如果两个数组相等则表示该排序算法通过测试,否则表示该排序算法未通过测试。

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

在这里插入图片描述

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

小结

  本文主要介绍了Java中常用的数组排序算法,包括冒泡排序、插入排序、选择排序、快速排序、归并排序和堆排序。通过对这些排序算法的源代码解析、应用场景案例、优缺点分析、类代码方法介绍和测试用例进行讲解,帮助读者更好地理解这些排序算法。在选择排序算法时,需要根据实际情况来选择最适合的排序算法,不同的排序算法各有优缺点。同时,为了验证排序算法的正确性和效率,可以编写相应的测试用例进行验证。

总结

  本文对数组排序的重要性进行了探讨,并介绍了Java中常用的排序算法,包括冒泡排序、插入排序、选择排序、快速排序、归并排序和堆排序。通过代码解析、应用场景案例、优缺点分析、类代码方法介绍和测试用例,详细介绍了每种算法的实现和优缺点,帮助读者更好地理解排序算法。最后,强调了选择最适合的排序算法的重要性,并给出了相应的测试用例,以验证排序算法的正确性和效率。

因此,对于开发者而言,在日常开发中,不能忽视数组排序的重要性。在选择排序算法时,需要根据实际情况来选择最适合的排序算法,以提高程序的性能和效率。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/26144.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线稳源极跟随 线性电源前端降压

功率MOSFET线性电源涉及跟随.ms14 根本原理是Vgs对Id的控制&#xff0c;Vgs越大&#xff0c;Id越大&#xff0c;反之亦然。 观察转移特性曲线&#xff0c;结合接线图可知&#xff0c;电路稳定后&#xff0c;如果负载电阻增大&#xff0c;则Vsgnd增大&#xff0c;由于Vggnd有稳…

ONNX2NCNN工具

最近部署很多onnx转ncnn的操作&#xff0c;发现还是需要有页面操作会比较好&#xff0c;而且需要查询onnx的图&#xff0c;所以写了一个工具来搭配使用 建议搭配Netron 来使用 打开模型 选择打开-》选择onnx模型 显示基础信息 查询onnx模型图 展示信息 点击“展示信息”&…

vb.net小demo(计算器、文件处理等/C#也可看)

Demo1&#xff1a;使用窗体控件实现一个简易版计算器 Public Class Form1Private Sub Button_1_Click(sender As Object, e As EventArgs) Handles Button_1.ClickCalSubBox.Text Button_1.TextEnd SubPrivate Sub Button_2_Click(sender As Object, e As EventArgs) Handles …

B端系统的颜值问题:成也框架,败也框架!

B端UI框架和前端框架的出现&#xff0c;让系统的搭建就像堆积木一样&#xff0c;十分的容易了。这也一下子把程序员的设计和审美水平拔高到了UI框架能够达到的高度。伴随而来的则是系统的堆砌、同质化、糟糕的体验&#xff0c;以及各种违和的组件被生搬硬套的绑定在一块&#x…

nosql数据库的特点

NoSQL简介 NoSQL是一种不同于关系数据库的数据库管理系统设计方式,是对非关系型数据库的统称,它所采用的数据模型并非传统关系数据库的关系模型,而是类似键/值、列族、文档等非关系模型。NoSQL数据库没有固定的表结构,通常也不存在连接操作,也没有严格遵守ACID约束。因此…

虚拟机开启网络代理设置

前言&#xff1a; 不管是物理主机还是实验环境中的VMware虚拟机&#xff0c;有时候总要访问一些镜像网站或者资源网站拉取一些学习资料&#xff0c;但由于国内外网络环境的差异和网络安全的问题。总是会被阻拦。物理机相对比较容易一些&#xff0c;今天我们来说一说虚拟机应该…

YOLOv8模型训练参数详细解析

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

酷暑骄阳,热情似火丨deepin校园联盟走进湖北大学,共话开源新篇章

内容来源&#xff1a;deepin&#xff08;深度&#xff09;社区 炎炎夏日&#xff0c;骄阳似火&#xff0c;6月11日&#xff0c;deepin校园联盟湖北大学站交流活动如期举行。在湖北大学计算机与信息工程学院&#xff0c;deepin(深度)社区研发工程师王溢学为热情似火的学子们开展…

【LeetCode滑动窗口算法】长度最小的子数组 难度:中等

我们先看一下题目描述&#xff1a; 解法一&#xff1a;暴力枚举 时间复杂度&#xff1a;o(n^3) class Solution { public:int minSubArrayLen(int target, vector<int>& nums){int i 0, j 0;vector<int> v;for (;i < nums.size();i){int sum nums[i];fo…

HarmonyOS(34) @Track使用指南

Track Track概述使用案例使用条件 Track概述 Track是class对象的属性装饰器。当一个class对象是状态变量时&#xff08;也就是使用State修饰时&#xff09;&#xff0c;Track装饰的属性发生变化&#xff0c;只会触发该属性关联的UI更新&#xff1b;而未被标记的属性不能在UI中…

python-windows10普通笔记本跑bert mrpc数据样例0.1.048

python-windows10普通笔记本跑bert mrpc数据样例0.1.000 背景参考章节获取数据下载bert模型下载bert代码windows10的cpu进行训练进行预测注意事项TODOLIST背景 看了介绍说可以在gpu或者tpu上去微调,当前没环境,所以先在windows10上跑一跑,看是否能顺利进行,目标就是训练的…

如何免费用 Qwen2 辅助你翻译与数据分析?

对于学生用户来说&#xff0c;这可是个好消息。 开源 从前人们有一种刻板印象——大语言模型里好用的&#xff0c;基本上都是闭源模型。而前些日子&#xff0c;Meta推出了Llama3后&#xff0c;你可能已经从中感受到现在开源模型日益增长的威力。当时我也写了几篇文章来介绍这个…

Mysql查询分析工具Explain的使用

一、前言 作为一名合格的开发人员&#xff0c;与数据库打交道是必不可少的&#xff0c;尤其是在业务规模和数据体量大规模增长的条件下&#xff0c;应用系统大部分请求读写比例在10:1左右&#xff0c;而且插入操作和一般的更新操作很少出现性能问题&#xff0c;遇到最多的&…

力扣42 接雨水

听说字节每人都会接雨水&#xff0c;我也要会哈哈哈 数据结构&#xff1a;数组 算法&#xff1a;核心是计算这一列接到多少雨水&#xff0c;它取决于它左边的最大值和右边的最大值&#xff0c;如下图第三根柱子能接到的雨水应该是第一根柱子高度和第五根柱子高度的最小值减去第…

Win10超清图库

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl Win10每次锁屏时&#xff0c;系统都会展现一张背景图。其实这就是Windows 聚焦&#xff1b;图示如下&#xff1a; 这些图片不但精美&#xff0c;而且会每隔一段时间自动更新…

NFTScan 正式上线 Sei NFTScan 浏览器和 NFT API 数据服务

2024 年 6 月 12 号&#xff0c;NFTScan 团队正式对外发布了 Sei NFTScan 浏览器&#xff0c;将为 Sei 生态的 NFT 开发者和用户提供简洁高效的 NFT 数据搜索查询服务。NFTScan 作为全球领先的 NFT 数据基础设施服务商&#xff0c;Sei 是继 Bitcoin、Ethereum、BNBChain、Polyg…

从爱好到收入AI贴纸变现的五种途径,你尝试过几种?你会制作吗?

一、AI贴纸变现方式&#xff1a; 贴纸变现的方式主要包括以下几种&#xff1a; 1、广告变现 通过在小红书、公众号等可发图文的自媒体平台发布你制作的可爱贴纸&#xff0c;从而实现对可爱贴纸喜爱的人士观看并成为你的粉丝。粉丝达到一定数量即可接商业广告变现。 2、电商变…

Unity 实现WebSocket 简单通信——客户端

创建连接 ClientWebSocket socket new ClientWebSocket(); string url $"ws://{ip}:{port}"; bool createUri Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out Uri uri); if (createUri) {var task socket.ConnectAsync(uri, CancellationToken.None);task…

字符集相关变量理解

建表 创建一个新表&#xff0c;想让他的字符集是 gbk&#xff0c;怎么弄? 尝试1&#xff1a; 失败&#xff01;原因&#xff1a; set names gbk; 等价于&#xff1a;set character_set_client gbk; set character_set_connection gbk; set character_set_results gbk;尝…