排序算法(冒泡排序、选择排序、插入排序、希尔排序、堆排序、快速排序、归并排序、计数排序)

🍕博客主页:️自信不孤单

🍬文章专栏:数据结构与算法

🍚代码仓库:破浪晓梦

🍭欢迎关注:欢迎大家点赞收藏+关注

文章目录

  • 🍓冒泡排序
    • 概念
    • 算法步骤
    • 动图演示
    • 代码
  • 🍊选择排序
    • 概念
    • 算法步骤
    • 动图演示
    • 代码
  • 🍉插入排序
    • 概念
    • 算法步骤
    • 动图演示
    • 代码
  • ❣️希尔排序
    • 概念
    • 算法步骤
    • 动图演示
    • 代码
  • 🍥堆排序
    • 概念
    • 算法步骤
    • 动图演示
    • 代码
  • 🍚快速排序
    • 概念
    • 算法步骤
    • 动图演示
    • 代码(递归)
    • 代码(非递归)
  • 🍕归并排序
    • 概念
    • 算法步骤
    • 动图演示
    • 代码
    • 代码(非递归)
  • 🍭计数排序
    • 概念
    • 算法步骤
    • 动图演示
    • 代码
  • 🍧排序算法复杂度及稳定性


🍓冒泡排序

概念

冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

作为最简单的排序算法之一,冒泡排序给我的感觉就像 Abandon 在单词书里出现的感觉一样,每次都在第一页第一位,所以最熟悉。冒泡排序还有一种优化算法,就是立一个 flag,当在一趟序列遍历中元素没有发生交换,则证明该序列已经有序。但这种改进对于提升性能来说并没有什么太大作用。

算法步骤

比较相邻的元素。如果第一个比第二个大,就交换他们两个。

对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

针对所有的元素重复以上的步骤,除了最后一个。

持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

动图演示

在这里插入图片描述

代码

void bubble_sort(int arr[], int len)
{
    int i, j, temp, flag;
    for (i = 0; i < len - 1; i++)
    {
        flag = 1;
        for (j = 0; j < len - 1 - i; j++)
            if (arr[j] > arr[j + 1])
            {
                flag = 0;
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        if (flag)
            return;
    }
}

🍊选择排序

概念

选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。

算法步骤

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。

再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

重复第二步,直到所有元素均排序完毕。

动图演示

在这里插入图片描述

代码

void swap(int* a, int* b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

void selection_sort(int arr[], int len)
{
    int i, j;
    for (i = 0; i < len - 1; i++)
    {
        int min = i;
        for (j = i + 1; j < len; j++)
            if (arr[j] < arr[min])
                min = j;
        swap(&arr[min], &arr[i]);
    }
}

🍉插入排序

概念

插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

算法步骤

将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

动图演示

在这里插入图片描述

代码

void insertion_sort(int arr[], int len)
{
    int i, j, key;
    for (i = 1; i < len; i++) {
        key = arr[i];
        j = i - 1;
        while ((j >= 0) && (arr[j] > key))
        {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

❣️希尔排序

概念

希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  • 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
  • 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;

希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。

算法步骤

选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;

按增量序列个数 k,对序列进行 k 趟排序;

每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

动图演示

在这里插入图片描述

代码

void shell_sort(int arr[], int len)
{
    int gap, i, j;
    int temp;
    for (gap = len >> 1; gap > 0; gap >>= 1)
        for (i = gap; i < len; i++)
        {
            temp = arr[i];
            for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap)
                arr[j + gap] = arr[j];
            arr[j + gap] = temp;
        }
}

🍥堆排序

概念

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:

  1. 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
  2. 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;

堆排序的平均时间复杂度为 Ο(nlogn)。

算法步骤

  1. 创建一个堆;
  2. 把堆首(最大值)和堆尾互换;
  3. 把堆的大小缩小 1,并调用向下调整函数,目的是把新的数组顶端数据调整到相应位置;
  4. 重复步骤 2、3,直到堆的大小为 1。

动图演示

在这里插入图片描述

代码

void swap(int* a, int* b)
{
    int temp = *b;
    *b = *a;
    *a = temp;
}

void adjust_down(int* a, int start, int end)
{
    int parent = start;
    int child = parent * 2 + 1;
    while (child <= end)
    {
        if (child + 1 <= end && a[child] < a[child + 1])
            child++;

        if (a[parent] < a[child])
        {
            swap(&a[parent], &a[child]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
            return;
    }
}

void heap_sort(int a[], int len)
{
    for (int i = (len - 1 - 1) / 2; i >= 0; i--)
        adjust_down(a, i, len - 1);

    for (int i = len - 1; i > 0; i--)
    {
        swap(&a[0], &a[i]);
        adjust_down(a, 0, i - 1);
    }
}

🍚快速排序

概念

快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要 Ο(nlogn) 次比较。在最坏状况下则需要 Ο(n2) 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。

快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。

快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。

算法步骤

  1. 从数列中挑出一个元素,称为 “基准”(pivot);
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

动图演示

在这里插入图片描述

代码(递归)

void swap(int* a, int* b)
{
    int temp = *b;
    *b = *a;
    *a = temp;
}

// 三数取中
int get_mid(int* a, int left, int right)
{
    int mid = (left + right) / 2;
    if (a[left] > a[mid])
    {
        if (a[mid] > a[right])
            return mid;
        else if (a[right] > a[left])
            return left;
        else
            return right;
    }
    else
    {
        if (a[left] > a[right])
            return left;
        else if (a[mid] < a[right])
            return mid;
        else
            return right;
    }
}

// 快速排序hoare法
int part_sort1(int* a, int left, int right)
{

    int mid = get_mid(a, left, right);
    swap(&a[mid], &a[left]);
    int keyi = left;
    while (right > left)
    {
        while (right > left && a[right] >= a[keyi])
        {
            right--;
        }
        while (right > left && a[left] <= a[keyi])
        {
            left++;
        }
        swap(&a[left], &a[right]);
    }
    swap(&a[keyi], &a[left]);
    return left;
}

// 快速排序挖坑法
int part_sort2(int* a, int left, int right)
{
    int mid = get_mid(a, left, right);
    swap(&a[mid], &a[left]);
    int key = a[left];
    int hole = left;
    while (left < right)
    {
        while (left < right && a[right] > key)
        {
            right--;
        }
        a[hole] = a[right];
        hole = right;

        while (left < right && a[left] < key)
        {
            left++;
        }
        a[hole] = a[left];
        hole = left;
    }
    swap(&a[hole], &key);
    return hole;
}

// 快速排序前后指针法
int part_sort3(int* a, int left, int right)
{
    int mid = get_mid(a, left, right);
    swap(&a[mid], &a[left]);
    int keyi = left;
    int prev = left;
    int cur = left + 1;
    while (cur <= right)
    {
        if (a[cur] < a[keyi])
        {
            prev++;
            if (cur != prev)
                swap(&a[cur], &a[prev]);
        }
        cur++;
    }
    swap(&a[prev], &a[keyi]);
    return prev;
}

void quick_sort(int* a, int left, int right)
{
    if (left >= right)
    {
        return;
    }

    int keyi = part_sort1(a, left, right);
    //int keyi = part_sort2(a, left, right);
    //int keyi = part_sort3(a, left, right);
    
    quick_sort(a, left, keyi - 1);
    quick_sort(a, keyi + 1, right);
}

代码(非递归)

注:栈的结点定义和各接口函数

void quick_sort_non_r(int* a, int begin, int end)
{
    ST st;
    STInit(&st);
    STPush(&st, end);
    STPush(&st, begin);

    while (!STEmpty(&st))
    {
        int left = STTop(&st);
        STPop(&st);

        int right = STTop(&st);
        STPop(&st);

        int keyi = part_sort1(a, left, right);
        //int keyi = part_sort2(a, left, right);
        //int keyi = part_sort3(a, left, right);

        if (keyi + 1 < right)
        {
            STPush(&st, right);
            STPush(&st, keyi + 1);
        }

        if (left < keyi - 1)
        {
            STPush(&st, keyi - 1);
            STPush(&st, left);
        }
    }

    STDestroy(&st);
}

🍕归并排序

概念

归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:

  • 自上而下的递归(所有递归的方法都可以用迭代重写,所以就有了第 2 种方法);
  • 自下而上的迭代;

和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是 O(nlogn) 的时间复杂度。代价是需要额外的内存空间。

算法步骤

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置;
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
  4. 重复步骤 3 直到某一指针达到序列尾;
  5. 将另一序列剩下的所有元素直接复制到合并序列尾。

动图演示

在这里插入图片描述

代码

void _merge_sort(int* a, int begin, int end, int* tmp)
{
    if (begin == end)
        return;

    int mid = (begin + end) / 2;
    
    _merge_sort(a, begin, mid, tmp);
    _merge_sort(a, mid + 1, end, tmp);

    int begin1 = begin, end1 = mid;
    int begin2 = mid + 1, end2 = end;
    
    int i = begin;
    
    while (begin1 <= end1 && begin2 <= end2)
    {
        if (a[begin1] <= a[begin2])
        {
            tmp[i++] = a[begin1++];
        }
        else
        {
            tmp[i++] = a[begin2++];
        }
    }

    while (begin1 <= end1)
    {
        tmp[i++] = a[begin1++];
    }

    while (begin2 <= end2)
    {
        tmp[i++] = a[begin2++];
    }

    memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}

void merge_sort(int* a, int n)
{
    int* tmp = (int*)malloc(sizeof(int) * n);
    
    if (tmp == NULL)
    {
        return;
    }

    _merge_sort(a, 0, n - 1, tmp);
    free(tmp);
}

代码(非递归)

void _merge_sort_non_r(int* a, int n, int* tmp)
{
    int gap = 1;
    int begin = 0;
    while (gap < n)
    {
        int j = 0;
        for (int i = 0; i < n; i += 2 * gap)
        {
            int begin1 = i, end1 = i + gap - 1;
            int begin2 = i + gap, end2 = i + 2 * gap - 1;


            if (end1 >= n || begin2 >= n)
            {
                break;
            }

            if (end2 >= n)
            {
                end2 = n - 1;
            }

            while (begin1 <= end1 && begin2 <= end2)
            {
                if (a[begin1] <= a[begin2])
                {
                    tmp[j++] = a[begin1++];
                }
                else
                {
                    tmp[j++] = a[begin2++];
                }
            }

            while (begin1 <= end1)
            {
                tmp[j++] = a[begin1++];
            }

            while (begin2 <= end2)
            {
                tmp[j++] = a[begin2++];
            }
            memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));
        }

        gap *= 2;
    }
}

void merge_sort_non_r(int* a, int n)
{
    int* tmp = (int*)malloc(sizeof(int) * n);

    if (tmp == NULL)
    {
        return;
    }

    _merge_sort_non_r(a, n, tmp);
    free(tmp);
}

🍭计数排序

概念

计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。

当输入的元素是 n 个 0 到 k 之间的整数时,它的运行时间是 O(n + k)。计数排序不是比较排序,排序的速度快于任何比较排序算法。

由于用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),这使得计数排序对于数据范围很大的数组,需要大量时间和内存。例如:计数排序是用来排序0到100之间的数字的最好的算法,但是它不适合按字母顺序排序人名。但是,计数排序可以用在基数排序中的算法来排序数据范围很大的数组。

算法步骤

  1. 找出待排序的数组中最大和最小的元素;
  2. 统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
  3. 对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
  4. 填充目标数组:将每个元素i放在新数组中,每放一个元素就将C(i)减去1,减到0再去放下一个i。

动图演示

在这里插入图片描述

代码

void count_sort(int* a, int n)
{
	int min = a[0], max = a[0];
	for (int i = 0; i < n; i++)
	{
		if (a[i] < min)
		{
			min = a[i];
		}

		if (a[i] > max)
		{
			max = a[i];
		}
	}

	int range = max - min + 1;
	int* count = (int*)malloc(sizeof(int) * range);
    if(count == NULL)
        return;
    
	memset(count, 0, sizeof(int) * range);

	// 统计次数
	for (int i = 0; i < n; i++)
	{
		count[a[i] - min]++;
	}

	// 排序
	int k = 0;
	for (int j = 0; j < range; j++)
	{
		while (count[j]--)
		{
			a[k++] = j + min;
		}
	}
    
    free(count);
}

🍧排序算法复杂度及稳定性

排序算法平均情况最好情况最坏情况辅助空间稳定性
冒泡排序 O ( n 2 ) O(n^2) O(n2) O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)稳定
简单选择排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)不稳定
直接插入排序 O ( n 2 ) O(n^2) O(n2) O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)稳定
希尔排序 O ( n log ⁡ n ) ~ O ( n 2 ) O(n\log n) ~O(n^2) O(nlogn)O(n2) O ( n 1.3 ) O(n^{1.3}) O(n1.3) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)不稳定
堆排序 O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( 1 ) O(1) O(1)不稳定
快速排序 O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n 2 ) O(n^2) O(n2) O ( log ⁡ n ) ~ O ( n ) O(\log n) ~O(n) O(logn)O(n)不稳定
归并排序 O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n ) O(n) O(n)稳定
计数排序 O ( n + r a n g e ) O(n+range) O(n+range) O ( n + r a n g e ) O(n+range) O(n+range) O ( n + r a n g e ) O(n+range) O(n+range) O ( r a n g e ) O(range) O(range)稳定

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数学建模学习(7):Matlab绘图

一、二维图像绘制 1.绘制曲线图 最基础的二维图形绘制方法&#xff1a;plot -plot命令自动打开一个图形窗口Figure&#xff1b; 用直线连接相邻两数据点来绘制图形 -根据图形坐标大小自动缩扩坐标轴&#xff0c;将数据标尺及单位标注自动加到两个坐标轴上&#xff0c;可自定…

【Linux】sed修改文件指定内容

sed修改文件指定内容&#xff1a; 参考&#xff1a;(5条消息) Linux系列讲解 —— 【cat echo sed】操作读写文件内容_shell命令修改文件内容_星际工程师的博客-CSDN博客

理解构建LLM驱动的聊天机器人时的向量数据库检索的局限性 - (第1/3部分)

本博客是一系列文章中的第一篇&#xff0c;解释了为什么使用大型语言模型&#xff08;LLM&#xff09;部署专用领域聊天机器人的主流管道成本太高且效率低下。在第一篇文章中&#xff0c;我们将讨论为什么矢量数据库尽管最近流行起来&#xff0c;但在实际生产管道中部署时从根本…

【编译】gcc make cmake Makefile CMakeList.txt 区别

文章目录 一 关系二 gcc2.1 编译过程2.2 编译参数2.3 静态库和动态库1 后缀名2 联系与区别 2.4 GDB 调试器1 常用命令 三 make、makefile四 cmake、cmakelist4.1 语法特性4.2 重要命令4.2 重要变量4.3 编译流程4.4 两种构建方式 五 Vscode5.0 常用快捷键5.1 界面5.2 插件5.3 .v…

点播播放器如何自定义额外信息(统计信息传值)

Web播放器支持设置观众信息参数&#xff0c;设置后在播放器上报的观看日志中会附带观众信息&#xff0c;这样用户就可以通过管理后台的统计页面或服务端API来查看特定观众的视频观看情况了。 播放器设置观众信息参数的代码示例如下&#xff1a; <div id"player"…

加利福尼亚大学|3D-LLM:将3D世界于大规模语言模型结合

来自加利福尼亚大学的3D-LLM项目团队提到&#xff1a;大型语言模型 (LLM) 和视觉语言模型 (VLM) 已被证明在多项任务上表现出色&#xff0c;例如常识推理。尽管这些模型非常强大&#xff0c;但它们并不以 3D 物理世界为基础&#xff0c;而 3D 物理世界涉及更丰富的概念&#xf…

【100天精通python】Day20:文件及目录操作_os模块和os.psth模块,文件权限修改

目录 专栏导读 1 文件的目录操作 os模块的一些操作目录函数​编辑 os.path 模块的操作目录函数 2 相对路径和绝对路径 3 路径拼接 4 判断目录是否存在 5 创建目录、删除目录、遍历目录 专栏导读 专栏订阅地址&#xff1a;https://blog.csdn.net/qq_35831906/category_12…

Java中的代理模式

Java中的代理模式 1. 静态代理JDK动态代理CGLib动态代理 1. 静态代理 接口 public interface ICeo {void meeting(String name) throws InterruptedException; }目标类 public class Ceo implements ICeo{public void meeting(String name) throws InterruptedException {Th…

【信号去噪和正交采样】流水线过程的一部分,用于对L波段次级雷达中接收的信号进行降噪(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

计算机网络——应用层

文章目录 **1 网络应用模型****2 域名系统DNS****3 文件传输协议FTP****4 电子邮件****4.1 电子邮件系统的组成结构****4.2 电子邮件格式与MIME****4.3 SMTP和POP3** **5 万维网WWW****5.1 HTTP** 1 网络应用模型 客户/服务器模型 C/S 服务器服务于许多来自其他称为客户机的主…

uniapp跨域解决

uniapp跨域解决 跨域是什么 跨域指的是浏览器不能执行其他网站的脚本&#xff0c;当一个网页去请求另一个域名的资源时&#xff0c;域名、端口、协议任一不同&#xff0c;就会存在跨域。跨域是由浏览器的同源策略造成的&#xff0c;是浏览器对JavaScript施加的安全限制。 报错…

Spring AOP 中,切点有多少种定义方式?

在 Spring AOP 中&#xff0c;我们最常用的切点定义方式主要是两种&#xff1a; 使用 execution 进行无侵入拦截。使用注解进行拦截。 这应该是是小伙伴们日常工作中使用最多的两种切点定义方式了。但是除了这两种还有没有其他的呢&#xff1f;今天松哥就来和大家聊一聊这个话…

【C语言初阶(20)】调试练习题

文章目录 前言实例1实例2 前言 在我们开始调试之前&#xff0c;应该有个明确的思路&#xff1b;程序是如何完成工作的、变量到达某个步骤时的值应该是什么、出现的问题大概会在什么位置。这些东西在调试之前都需要先确认下来&#xff0c;不然自己都不知道自己在调试个什么东西…

FFmpeg aresample_swr_opts的解析

ffmpeg option的解析 aresample_swr_opts是AVFilterGraph中的option。 static const AVOption filtergraph_options[] {{ "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS,{ .i64 AVFILTER_THREAD_SLICE }, 0, INT_MA…

二十三种设计模式第二十篇--备忘录模式

备忘录模式&#xff0c;备忘录模式属于行为型模式。它允许在不破坏封装的情况下捕获和恢复对象的内部状态。保存一个对象的某个状态&#xff0c;以便在适当的时候恢复对象&#xff0c;该模式通过创建一个备忘录对象来保存原始对象的状态&#xff0c;并将其存储在一个负责管理备…

使用adb通过电脑给安卓设备安装apk文件

最近碰到要在开发板上安装软件的问题&#xff0c;由于是开发板上的安卓系统没有解析apk文件的工具&#xff0c;所以无法通过直接打开apk文件来安装软件。因此查询各种资料后发现可以使用adb工具&#xff0c;这样一来可以在电脑上给安卓设备安装软件。 ADB 就是连接 Android 手…

测试libcurl库的demo时,报错 curl_easy_perform() failed: SSL connect error

系统&#xff1a;麒麟V10 arm roothg-TR3250:/home/cur765/curl-7.65.3/docs/examples# cat /etc/os-release NAME"Kylin" VERSION"银河麒麟桌面操作系统(国防版)V10" VERSION_US"Kylin Linux Desktop (GFB)V10" IDkylin ID_LIKEdebian PRETT…

CloudDriver一款将各种网盘云盘挂在到电脑本地变成本地磁盘的工具 教程

平时我们的电脑可能由于大量的文件资料之类的导致存储空间可能不够&#xff0c;所以我们可以选择将网盘我们的本地磁盘用来存放东西。 CloudDrive 是一款可以将 115、阿里云盘、天翼云盘、沃家云盘、WebDAV 挂载到电脑中&#xff0c;成为本地硬盘的工具&#xff0c;支持 Window…

职工管理系统(code)

首先创建头文件、源文件&#xff0c;再编程。&#xff08;B站黑马程序员视频笔记&#xff09; 一、头文件.h 1、boss.h #pragma once #include<iostream> using namespace std; #include "worker.h"//老板类 class Boss :public Worker { public://构造函数B…