Java 数据结构篇-深入了解排序算法(动态图 + 实现七种基本排序算法)

news2025/1/16 17:00:53

 🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍
  

文章目录

        1.0 实现冒泡排序

        2.0 实现选择排序

        2.1 选择排序的改良升级

        3.0 实现堆排序

        4.0 实现插入排序

        5.0 实现希尔排序

        6.0 实现归并排序

        6.1 递归实现归并排序

        6.2 使用非递归实现归并排序

        6.3 递归归并排序 + 插入排序

        7.0 快速排序

        7.1 单边循环快排

        7.2 双边循环快排

        7.3 快速排序的改良升级


        1.0 实现冒泡排序

        冒泡排序是一种简单的排序算法,它重复地遍历要排序的列表,比较相邻的元素,并交换它们直到列表排序完成。冒泡排序的时间复杂度为 O(n^2) ,在最坏的情况下需要进行 n*(n-1)/2 次比较和交换操作。是一个稳定排序。

具体步骤如下:

         -从列表的第一个元素开始,依次比较相邻的两个元素,如果它们的顺序不正确,则交换它们的位置。

        - 继续比较相邻的元素,直到达到列表的末尾。

        - 重复以上步骤,直到列表排序完成。

冒泡排序的详解过程:

        冒泡排序的过程可以用一个简单的示意图来说明,假设我们要对一个包含5个元素的列表进行冒泡排序:

        初始状态: [5, 3, 8, 2, 1]

        第一轮冒泡:比较相邻的元素并交换它们的位置,直到最大的元素被“冒泡”到列表的末尾。[3, 5, 2, 1, 8] ,[x, x, x, x, 8] 所在的位置就是最终的位置,因此不需要再进行交换了。

        第二轮冒泡:同样比较相邻的元素并交换它们的位置,直到最大的元素被“冒泡”到列表的末尾。[3, 2, 1, 5, 8] , [x, x, x, 5, 8] 所在的位置就是最终的位置,因此不需要再进行交换了。

        第三轮冒泡:同理,[2, 1, 3, 5, 8] , [x, x, 3, 5, 8] 所在的位置就是最终的位置,因此不需要再进行交换了。

        第四轮冒泡:[1, 2, 3, 5, 8] 完成排序了,一共需要进行(数组长度 - 1 )轮冒泡。

        

  数组的顺序为 [8,7,6,5,4,3,2,1] 来进行冒泡排序的动态演示过程:

        

代码如下:

import java.util.Arrays;

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {1,10,7,4,8,3,2,6,9,5};
        bubble(arr);
        System.out.println(Arrays.toString(arr));
    }

    //冒泡排序
    public static void bubble(int[] arr) {
        for (int i = 0;i < arr.length-1; i++) {
            for (int j = 0 ;j < arr.length-1-i;j++) {
                if (arr[j] > arr[j+1]) {
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
    }
}

        2.0 实现选择排序

        选择排序(Selection Sort)是一种简单直观的排序算法。选择排序的时间复杂度为 O(n^2) ,因为在每一轮中需要进行n次比较,找到最小元素。(默认从小到大排序)

       基本思想:每次从待排序的数据元素中选出最小(或最大)的一个元素,然后放到已排序序列的末尾。内层循环代表的是:当前这次循环中,需要找到剩余数组中最小的元素;外层循坏代表的是:需要进行多少次内层循环,才能将数组中的元素按从小到大排序完成。

举例详解选择过程:

        初识状态:[3, 44, 5, 27, 2, 50, 48]

        第一轮选择过程:记录未排好序的元素 3 ,然后从元素 3 的后一个元素 44 出发,寻找比 3 小的元素,如果找到了,则需要进行交换;如果没有找到,这说明元素 3 就是当前循环过程中最小的元素。当前找到了比元素 3 小的元素 2 ,那么需要进行交换。

        第二轮选择过程:因为元素 2 已经排好序了,那么需要记录从排好序元素的后一个元素 44 ,寻找的范围是当前记录的元素的后一个元素开始出发直到数组最后一个元素。同样,重复以上操作,如果找到了比 44 要小的元素,需要进行记录 minIndex = i ,内层循环结束后,最小的元素下标为 minIndex  ,交换 44 与下标为 minIndex 的元素。

        第三轮选择过程也是一样流程,这里就不多赘述了......

选择过程的动态图演示过程:

代码如下:

import java.util.Arrays;

public class SelectSort {
    public static void main(String[] args) {
        int[] arr = {1,10,7,4,8,3,2,6,9,5};
        select1(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void select1(int[] arr) {

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

}

        2.1 选择排序的改良升级

        在选择过程中,内层循环每一次都是寻找最小的元素,这次改进是在寻找最小元素的同时,又找最大的元素,定义两个 letf ,right 指针,一开始分别指向数组的左右两边。此时外层的循环条件:left < right 。一次内层循环中找到了最小、最大元素,接着就分别于 left、right 下标元素进行交换,交换完之后,left++ ,right-- 。

        一开始 minIndex、maxIndex 都是从 left 开始,从左到右进行查找元素的。重点需要需要注意的是:假如最大的元素就是当前的 left 下标时,且 minIndex 与 left 进行交换后,会导致 maxIndex 找的元素下标就会发生变化,所以在下标 minIndex 与 left 交换完之后,需要判断 maxInde == left 是否发生,如果发生了,那么 maxIndex 需要重新赋值为 maxIndex = minIndex 。

代码如下:

import java.util.Arrays;

public class SelectSort {
    public static void main(String[] args) {
        int[] arr = {1,10,7,4,8,3,2,6,9,5};
        select2(arr);
        System.out.println(Arrays.toString(arr));
    }
   
    public static void swap(int[] arr,int i,int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void select2(int[] arr) {
        int left = 0;
        int right = arr.length-1;
        while (left < right) {
            int minIndex = left;
            int maxIndex = left;

            for (int i = left+1;i <= right; i++) {
                if (arr[i] < arr[minIndex]) {
                    minIndex = i;
                }
                if (arr[i] > arr[maxIndex]) {
                    maxIndex = i;
                }
            }
            swap(arr,minIndex,left);
            if (maxIndex == left) {
                maxIndex = minIndex;
            }
            swap(arr,maxIndex,right);
            left++;
            right--;
        }
    }

}

        3.0 实现堆排序

        堆排序(Heap Sort)是一种高效的排序算法,它利用了堆这种数据结构来实现排序。堆是一种特殊的完全二叉树,分为最大堆和最小堆两种类型。在堆排序中,通常使用最大堆。堆排序的时间复杂度为 O(nlogn) ,并且是原地排序算法,不需要额外的存储空间。

        堆排序的基本思想:首先将待排序的数据构建成一个最大堆,然后将堆顶元素(最大元素)与堆的最后一个元素交换,然后对剩余的元素重新调整为最大堆,重复这个过程直到整个序列有序。

        两个动作:首先是将数组中的元素构建成一个大顶堆的形式,接着从堆的最后一个元素与堆顶元素进行交换,再对当前的堆顶元素进行下潜处理,循环该过程即可。

堆排序的动态演示过程:(该过程演示的是降序的排序过程,那么相反,建立一个小顶堆)

代码如下:

建立大顶堆的代码:下潜、交换元素

class Heap {
    int[] arr;
    int size = 0;

    public Heap(int[] arr) {
        this.arr = arr;
        this.size = arr.length;
        buildBigHeap(arr,size);
        heapSort(arr);
    }

    public void buildBigHeap(int[] arr,int size) {
        for (int i = size / 2 - 1; i >= 0 ; i--) {
            down(i,size);
        }
    }
    private void down(int i,int size) {
        int left = i * 2 + 1;
        int right = left + 1;
        int max = i;
        if (left < size && arr[max] < arr[left]) {
            max = left;
        }
        if (right < size && arr[max] < arr[right]) {
            max = right;
        }
        if (max != i) {
            swap(arr,max,i);
            down(max,size);
        }

    }
    private void swap(int[] arr,int i,int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

}

堆排序的完整代码:

import java.util.Arrays;

public class HeapSort {
    public static void main(String[] args) {
        int[] arr = {1,10,7,4,8,3,2,6,9,5};
        Heap heap = new Heap(arr);
        System.out.println(Arrays.toString(arr));
    }
}
class Heap {
    int[] arr;
    int size = 0;

    public Heap(int[] arr) {
        this.arr = arr;
        this.size = arr.length;
        buildBigHeap(arr,size);
        heapSort(arr);
    }

    public void buildBigHeap(int[] arr,int size) {
        for (int i = size / 2 - 1; i >= 0 ; i--) {
            down(i,size);
        }
    }
    private void down(int i,int size) {
        int left = i * 2 + 1;
        int right = left + 1;
        int max = i;
        if (left < size && arr[max] < arr[left]) {
            max = left;
        }
        if (right < size && arr[max] < arr[right]) {
            max = right;
        }
        if (max != i) {
            swap(arr,max,i);
            down(max,size);
        }
    }
    private void swap(int[] arr,int i,int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public void heapSort(int[] arr) {
        for (int i = arr.length - 1; i > 0 ; i--) {
            swap(arr,i,0);
            down(0,i);
        }
    }

}

        4.0 实现插入排序

        插入排序是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对未排序的数据逐个进行插入,从而达到排序的目的。插入排序的时间复杂度为 O(n^2) ,在最坏情况下(逆序排列的数组),需要进行 n*(n-1)/2 次比较和交换操作。插入排序适用于小规模数据或部分有序的数据。是一个稳定排序。

具体来说,插入排序的算法步骤如下:

        1.从第一个元素开始,该元素可以认为已经被排序。

        2.取出下一个元素,在已经排序的元素序列中从后向前扫描。

        3.如果该元素(已排序)大于新元素,将该元素移到下一位置。

        4.重复步骤3,直到找到已排序的元素小于或等于新元素的位置。

        5.将新元素插入到该位置后。

        6.重复步骤2~5。

插入排序动态图演示过程:

代码如下:

import java.util.Arrays;

public class InsertSort {
    public static void main(String[] args) {
        int[] arr = {1,10,7,4,8,3,2,6,9,5};
        insert(arr);
        System.out.println(Arrays.toString(arr));
    }
    
    public static void insert(int[] arr) {

        for (int i = 1; i < arr.length; 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;
        }
    }
    
}

        5.0 实现希尔排序

        希尔排序(Shell Sort)是一种改进的插入排序算法,也被称为“缩小增量排序”。它通过将数组分割成若干个子序列,对每个子序列进行插入排序,最终进行一次完整的插入排序得到有序序列。希尔排序的工作原理是通过逐步减小增量的方式,最终达到增量为1的插入排序。希尔排序的时间复杂度取决于增量序列的选择,通常为 O(n logn)

希尔排序的算法步骤如下:

        1. 选择一个增量序列,通常为 n/2、n/4、n/8……直到增量为 1 。

        2. 对每个增量进行插入排序,即将数组分割成若干个子序列,对每个子序列进行插入排序。

        3. 逐步缩小增量,重复步骤 2 ,直到增量为 1 。

        4. 最后进行一次增量为 1 的插入排序,完成排序过程。

希尔排序的动态演示过程:

代码如下:

import java.util.Arrays;

public class ShellSort {
    public static void main(String[] args) {
        int[] arr = {8,9,1,7,2,3,5,4,6,0};
        shell(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void shell(int[] arr) {
        int size = arr.length;
        for (int gap = size >> 1;gap >= 1; gap >>= 1) {
            for (int i = gap; i < size;i++) {
                int key = arr[i];
                int j = i-gap;
                while(j >= 0 && arr[j] > key) {
                    arr[j+gap] = arr[j];
                    j -= gap;
                }
                arr[j + gap] = key;
            }
        }
    }

}

        6.0 实现归并排序

        归并排序(Merge Sort)是一种经典的分治算法,它的基本思想是将待排序的数组递归地分成两个子数组,分别对两个子数组进行排序,然后将两个已排序的子数组合并成一个有序的数组。归并排序的过程可以描述为“分而治之”。

        归并排序是一种稳定的排序算法,它的时间复杂度始终为 O(n log n) ,这使得它在处理大规模数据时具有较好的性能。然而,归并排序的空间复杂度较高,因为它需要额外的空间来存储临时数组。

        6.1 递归实现归并排序

归并排序的算法步骤如下:

        1. 分:将待排序的数组分成两个子数组,直到子数组的长度为1。

        2. 治:对每个子数组进行递归排序,直到子数组有序。

        3. 合:将两个有序的子数组合并成一个有序的数组。

使用递归实现归并的动态演示过程:

代码如下:

import javax.print.DocFlavor;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.IllegalFormatCodePointException;

public class mergeSort {
    public static void main(String[] args) {
        int[] arr = {1,10,7,4,8,3,2,6,9,5};
        int[] a = new int[arr.length];
        //spilt(arr,0, arr.length - 1,a);
        //merge(arr);
        spiltInsert(arr,0,arr.length,a);
        System.out.println(Arrays.toString(arr));
    }


    //使用递归实现归并排序
    public static void spilt(int[] arr,int left,int right, int[] a) {
        if (left == right) {
            return;
        }
        //分
        int mid = (left + right) >>> 1;
        spilt(arr,left,mid,a);
        spilt(arr,mid+1,right,a);
        //合
        mergeArr(arr,left,mid,mid + 1,right,a);
        System.arraycopy(a,left,arr,left,right - left + 1);
    }

    //非递归实现两个有序数组合并
    public static void mergeArr(int[] arr,int i,int iEnd,int j,int jEnd,int[] a) {
        int k = i;
        while(i <= iEnd && j <= jEnd) {
            if (arr[i] < arr[j]) {
                a[k] = arr[i];
                i++;
            }else {
                a[k] = arr[j];
                j++;
            }
            k++;
        }
        if (i > iEnd) {
            System.arraycopy(arr,j,a,k,jEnd - j + 1);
        }
        if (j > jEnd) {
            System.arraycopy(arr,i,a,k,iEnd - i + 1);
        }
    }



}

         6.2 使用非递归实现归并排序

        非递归归并排序的关键是正确地计算子数组的大小并进行合并操作,直到整个数组都被合并为一个有序序列。

以下是非递归归并排序的主要步骤:

        1. 从数组中的每个元素开始,将其视为一个大小为1的有序序列。

        2. 通过迭代,将相邻的有序序列合并为更大的有序序列,直到整个数组变为一个有序序列。

        3. 在每次迭代中,合并的子数组大小以指数级增加,直到整个数组都被合并为一个有序序列。

代码如下:

    //使用递归实现归并排序
    public static void spilt(int[] arr,int left,int right, int[] a) {
        if (left == right) {
            return;
        }
        //分
        int mid = (left + right) >>> 1;
        spilt(arr,left,mid,a);
        spilt(arr,mid+1,right,a);
        //合
        mergeArr(arr,left,mid,mid + 1,right,a);
        System.arraycopy(a,left,arr,left,right - left + 1);
    }

    //非递归实现两个有序数组合并
    public static void mergeArr(int[] arr,int i,int iEnd,int j,int jEnd,int[] a) {
        int k = i;
        while(i <= iEnd && j <= jEnd) {
            if (arr[i] < arr[j]) {
                a[k] = arr[i];
                i++;
            }else {
                a[k] = arr[j];
                j++;
            }
            k++;
        }
        if (i > iEnd) {
            System.arraycopy(arr,j,a,k,jEnd - j + 1);
        }
        if (j > jEnd) {
            System.arraycopy(arr,i,a,k,iEnd - i + 1);
        }
    }

        6.3 递归归并排序 + 插入排序

        即集合了递归排序的优点与插入排序的优点实现更加高效排序。

代码如下:

    //递归归并 + 插入排序
    public static void spiltInsert(int[] arr,int left,int right,int[] a) {
        if (right - left <= 32) {
            insert(arr,left,right);
            return;
        }
        int m = (left + right) >>> 1;
        spiltInsert(arr,left,m,a);
        spiltInsert(arr,m+1,right,a);
        mergeArr(arr,left,m,m+1,right,a);
        System.arraycopy(a,left,arr,left,right-left+1);
    }
    //插入排序
    public static void insert(int[] arr,int left, int right) {
        for (int i = left + 1; i < right; i++) {
            int key = arr[i];
            int j = i - 1;
            while (j >= left && arr[j] > key) {
                arr[j+1] = arr[j];
                j--;
            }
            arr[j+1] = key;
        }
    }

        7.0 快速排序

        快速排序是一种常用的排序算法,它基于分治的思想。快速排序的基本思想是选择一个基准值,然后将数组分割成两部分,使得左边的元素都小于基准值,右边的元素都大于基准值。然后对左右两部分分别进行递归排序,直到整个数组有序。

以下是快速排序的主要步骤:

        1.选择一个基准值(通常是数组中的第一个元素)。

        2.将数组分割成两部分,使得左边的元素都小于基准值,右边的元素都大于基准值。这一步称为分区操作。

        3. 递归地对左右两部分进行快速排序。

        4. 当左右两部分都有序时,整个数组也就有序了。

        7.1 单边循环快排

        单边循环快排的时间复杂度为 O(n logn)空间复杂度为 O(logn)。单边循环快排(也称为荷兰国旗问题解法)是快速排序算法的一种实现方式,它通过使用单个指针在数组中进行循环遍历,实现数组的分区和排序。

代码如下:

//单边循环快排要点:
    //选择最右侧元素作为基准点
    //j 找比基准点小的,i 找基准点大的,一旦找到,二者进行交换:
    //                   交换时机: j 找到小的,且与 i 不相等
    //                   i 找到 >= 基准点元素后,不应自增
    // 最后基准点与 i 交换, i 即为基准点最终索引
    public static void quickSort(int[] arr) {
        recursion(arr,0,arr.length-1);
    }
    private static void recursion(int[] arr,int left,int right) {
        if (left >= right) {
            return;
        }
        //先找到基准点
        int m = benchmark(arr,left,right);
        //切分基准点两侧
        recursion(arr, left, m - 1);
        recursion(arr, m + 1, right);

    }
    private static int benchmark(int[] arr,int left,int right) {
        int temp = arr[right];
        //i 找最大值、 j 找最小值,一旦 j 找到最小值且 j != i 就可以交换了
        int i = left;
        int j = left;
        while (j < right) {
            if (arr[j] < temp) {
                if (i != j) {
                    //交换
                    swap(arr,i,j);
                }
                i++;
            }
            j++;
        }
        swap(arr,i,right);
        return i;
    }

    private static void swap(int[] arr,int i,int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

        7.2 双边循环快排

        双边循环快排是一种快速排序算法的实现方式,它通过不断地将数组分割成两部分并对每一部分进行递归排序来实现排序。与单边循环快排相比,双边循环快排在分割数组时使用两个指针分别从数组的两端向中间移动,以实现更高效的分割操作。

        双边循环快排的时间复杂度为 O(nlogn)空间复杂度为 O(logn)。它是一种高效的排序算法,在大多数情况下都能够快速地对数组进行排序。

具体实现过程如下:

        1. 选择数组中的一个元素作为基准值(通常选择第一个元素)。

        2. 设置两个指针,一个指向数组的起始位置,另一个指向数组的末尾位置。

        3. 从起始位置开始,找到第一个大于基准值的元素,并将其位置记录下来。

        4. 从末尾位置开始,找到第一个小于基准值的元素,并将其位置记录下来。

        5. 交换这两个元素的位置,然后继续寻找下一个需要交换的元素,直到两个指针相遇。

        6. 将基准值与指针相遇的位置的元素交换位置,这样基准值左边的元素都小于基准值,右边的元素都大于基准值。

        7. 对基准值左右两个子数组分别进行递归排序。

代码如下:

    //双边循环快排要点:
    //选择最左侧元素作为基准点
    //j 找比基准点小的, i 找比基准点大的,一旦找到,二者进行交换
    //       i 从左向右
    //       j 从右先左
    // 最后基准点与 i 交换, i 即为基准点最终索引
    public static void quickSort1(int[] arr) {
        recursion1(arr,0,arr.length-1);
    }
    private static void recursion1(int[] arr,int left,int right) {
        if (left >= right) {
            return;
        }
        int m = benchmark1(arr,left,right);
        recursion1(arr,left,m - 1);
        recursion1(arr,m + 1,right);

    }
    private static int benchmark1(int[] arr,int left,int right) {
        int temp = arr[left];
        int i = left;
        int j = right;
        while (i < j) {
            while (i < j && temp < arr[j]) {
                j--;
            }
            while (i < j && temp >= arr[i]) {
                i++;
            }
            swap(arr,i,j);
        }
        swap(arr,left,i);
        return i;
    }

    private static void swap(int[] arr,int i,int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

        7.3 快速排序的改良升级

        考虑快排时,遇到的重复元素过多而进行改良。

代码如下:

    public static void quickSort1(int[] arr) {
        recursion1(arr,0,arr.length-1);
    }
    private static void recursion1(int[] arr,int left,int right) {
        if (left >= right) {
            return;
        }
        int m = benchmark2(arr,left,right);
        recursion1(arr,left,m - 1);
        recursion1(arr,m + 1,right);

    }

    //考虑快排时,遇到的重复元素过多而进行改良
    private static int benchmark2(int[] arr,int left,int right) {
        int temp = arr[left];
        int i = left + 1;
        int j = right;
        while(i <= j) {
            while(i <= j && arr[i] < temp) {
                i++;
            }
            while (i <= j && arr[j] > temp ) {
                j--;
            }
            if (i <= j) {
                swap(arr,i,j);
                i++;
                j--;
            }
        }
        swap(arr,left,j);
        return j;
    }

 

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

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

相关文章

【misc | CTF】攻防世界 2017_Dating_in_Singapore

天命&#xff1a;这次终于碰到了算是真正的misc题目了 下载附件&#xff0c;打开是PDF&#xff0c;我一开始以为是flag隐写在PDF里面了 虽然也不奇怪&#xff0c;应该是可以的&#xff0c;毕竟PDF有xss漏洞也是可以的 言归正传&#xff0c;打开PDF 看着新加坡的日历&#xff…

汽车网络安全管理体系框架与评价-汽车网络安全管理体系框架

R155《网络安全与网络安全管理系统》法规中明确指出 &#xff0c; 汽车制造商应完成 “汽车网络安全管理体系认证” &#xff08;简称&#xff1a; CSMS认证&#xff09;以及 “车辆型式审批&#xff02; 且CSMS认证&#xff0c;是车辆型式审批的前提条件。 虽然我国相关政策尚…

走方格(动态规划)

解题思路&#xff1a; 找边界&#xff0c;即行为1&#xff0c;列为1。 拆分问题&#xff0c;拆分成一次走一步&#xff0c;只能向右或者向下走。 解题代码&#xff1a; public static void main(String[] args) {int [][]arrnew int[31][31];Scanner scnew Scanner(Sys…

贪吃蛇/链表实现(C/C++)

本篇使用C语言实现贪吃蛇小游戏&#xff0c;我们将其分为了三个大部分&#xff0c;第一个部分游戏开始GameStart&#xff0c;游戏运行GameRun&#xff0c;以及游戏结束GameRun。对于整体游戏主要思想是基于链表实现&#xff0c;但若仅仅只有C语言的知识还不够&#xff0c;我们还…

java基础:面向对象——类与对象初体验

本文需要援引一下我以前的博客做引言。 Python语言&#xff1a;面向对象——类与对象初体验 当使用Java进行面向对象编程的入门学习时&#xff0c;可以创建一个猫类来实践。 案例代码如下 package object; //使用class关键字创建一个猫类 class Car{ // 初始化类中的成员变量…

【工具推荐】磁盘分析工具 | SpaceSniffer 高效分析

文章目录 1 下载2 分析 最近发现一款很好用的工具——SpaceSniffer&#xff08;磁盘空间分析工具&#xff09; 硬盘用久了&#xff0c;里头的文件总是杂乱不堪&#xff0c;十分影响效率和心情&#xff1b; 我们往往会忘记哪些内容占用的空间比较多~所以我们如果可以高效分析哪…

YOLOv8-Seg改进:AIFI 助力YOLO ,提升尺度内和尺度间特征交互能力 | 来自于RT-DETR

🚀🚀🚀本文改进:RT-DETR的AIFI (尺度内特征交互)助力YOLO ,提升尺度内和尺度间特征交互能力 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你如何训练YOLOv8-seg; 2)模型创新,提升…

《AI 大模型全栈工程师》学习笔记1 - 大模型应用的技术架构

目录 1 前言 1.1 课程链接 1.2 名词解释&前置知识 2 大模型应用的技术架构 2.1 Prompt-Response架构 2.2 Agent Function Calling 架构 2.3 RAG&#xff08;Retrieval-Augmented Generation&#xff09;架构 2.4 Fine-tuning架构 1 前言 本文为知乎知学堂课程《A…

[机器学习]简单线性回归——梯度下降法

一.梯度下降法概念 2.代码实现 # 0. 引入依赖 import numpy as np import matplotlib.pyplot as plt# 1. 导入数据&#xff08;data.csv&#xff09; points np.genfromtxt(data.csv, delimiter,) points[0,0]# 提取points中的两列数据&#xff0c;分别作为x&#xff0c;y …

2024最新拼多多砍价群免费互帮助力群二维码秒进

拼多多天天领现金、现金大转盘、免费领商品等活动都是真实的&#xff0c;很多的网友都是体现成功了的&#xff0c;但是&#xff0c;这个钱想要领也是需要方法的&#xff0c;大家需要大量的群和新用户才可以完成操作。那我们怎么参加呢&#xff1f;今天小编就教大家几种方法&…

计算机毕业设计 | vue+springboot 超市账单管理系统(附源码)

1&#xff0c;绪论 1.1 开发背景 世界上第一个购物中心诞生于美国纽约&#xff0c;外国人迈克尔库伦开设了第一家合作商店&#xff0c;为了更好地吸引大量客流量&#xff0c;迈克尔库伦精心设计了低价策略&#xff0c;通过大量进货把商品价格压低&#xff0c;通过商店一次性集…

【Spark系列1】Spark作业执行原理

本文字数在7800字左右&#xff0c;预计时间在15分钟 一、整体流程 每个Aciton操作会创建一个JOB&#xff0c;JOB会提交给DAGScheduler&#xff0c;DAGScheduler根据RDD依赖的关系划分为多个Stage&#xff0c;每个Stage又会创建多个TaskSet&#xff0c;每个TaskSet包含多个Tas…

python简单socket demo

socket说明 socket本质是编程接口(API)&#xff0c;对TCP/IP的封装&#xff0c;TCP/IP也要提供可供程序员做网络开发所用的接口&#xff0c;这就是Socket编程接口。除了常见的http请求之外&#xff0c;一些敏感的数据传输常用socket套接字层直接传输数据。一个简单的domo用于熟…

基于Micropython利用ESP32-C3墨水屏电子时钟方法

本篇笔记介绍一下我们设计制作的墨水屏时钟。 1、所需硬件 1&#xff09;合宙的ESP32-C3&#xff1a; 2&#xff09;电子价签拆出来的2.9寸墨水屏&#xff1a; ——电子价签型号为&#xff1a;Stellar-L&#xff0c;墨水屏型号为&#xff1a;E029A01。 3&#xff09;自己设计…

我的2023年度总结

今天和去年一样&#xff0c;没有目录&#xff0c;正文开始&#xff1a; 距离上次更新博客已经过去很久了 我们还是不忘初心&#xff0c;先推荐一本书《培根随笔》。最近有想看马克思的著作&#xff0c;马哲才是世界大法。 这一年&#xff0c;过得很快。如果没有保持写日记的习惯…

多文件开发

当所有的类都写在main.m这个源文件之中、将不利于后期的维护和团队开发 推荐的方式 把1个类写在1个模块之中&#xff0c;而1个模块至少包含两个文件 h头文件 1.写的类声明因为要用到Foundation框架中的类NS0 bject所以在这个头文件中要引入 Foundationa 2.框架的头文件 3.然后…

1.23神经网络框架(sig函数),逆向参数调整法(梯度下降法,链式法则(理解,及处理多层神经网络的方式))

框架 输入层 隐藏层 存在一个阈值&#xff0c;如果低于某一阈值就不激活&#xff1b;高于了就激活 输出层 逆向参数调整方法 初始阶段&#xff0c;随机设置权重值w1,w2 依据训练集 两个数学方法 &#xff08;梯度下降、链式法则&#xff09; 调参借助两个数学方法 当导数为…

【归并排序】【图论】【动态规划】【 深度游戏搜索】1569将子数组重新排序得到同一个二叉搜索树的方案数

本文涉及知识点 动态规划汇总 图论 深度游戏搜索 归并排序 组合 LeetCoce1569将子数组重新排序得到同一个二叉搜索树的方案数 给你一个数组 nums 表示 1 到 n 的一个排列。我们按照元素在 nums 中的顺序依次插入一个初始为空的二叉搜索树&#xff08;BST&#xff09;。请你统…

了解OpenCV的数据类型

OpenCV是一个开源的计算机视觉库&#xff0c;广泛应用于图像和视频处理领域。在OpenCV中&#xff0c;数据类型扮演着非常重要的角色&#xff0c;它们决定了数据的存储方式和操作方式。本文将介绍OpenCV中常见的数据类型&#xff0c;包括图像数据类型、矩阵数据类型和轮廓数据类…

线程调度(Java Android)

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 未经允许不得转载 目录 一、导读二、概览2.1、线程的属性 三、…