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

news2024/9/23 8:33:41

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

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

🍚代码仓库:破浪晓梦

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

文章目录

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


🍓冒泡排序

概念

冒泡排序(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)稳定

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

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

相关文章

ED透明屏有哪些应用场景?

ED透明屏是一种新型的显示技术&#xff0c;它采用了电致变色技术&#xff0c;可以实现屏幕的透明显示。ED透明屏的出现&#xff0c;为我们的生活带来了许多便利和创新。 首先&#xff0c;ED透明屏可以应用于商业广告领域。 传统的广告牌往往是固定的&#xff0c;无法改变内容&…

浅入浅出MySQL事务

什么是事务 事务是由数据库中一系列的访问和更新组成的逻辑执行单元。 事务的逻辑单元中可以是一条SQL语句&#xff0c;也可以是一段SQL逻辑&#xff0c;这段逻辑要么全部执行成功&#xff0c;要么全部执行失败。 事务处理的基本原则是“原子性”、“一致性”、“隔离性”和…

vue 修改端口号

在根目录创建一个vue.config.js文件夹 module.exports {lintOnSave: false,devServer: {port: 3000,open: true} }运行后

降压IC 外置MOS DC48V转24V 3A 30V-80V转24V 3A 高压大功率

摘要&#xff1a;本文介绍了AH8A50QA降压IC外置MOS芯片方案&#xff0c;可将输入电压范围从30V至80V和9V至100V转换为24V输出&#xff0c;并提供最大3A的输出电流。该芯片方案采用了内置MOS管和QFN-20封装&#xff0c;适用于电动车和汽车车载充电源等高压大功率应用场景。 随着…

Cpp6 — 模板

模板&#xff1a;这里有一个概念&#xff1a;泛型编程---针对广泛的类型去写代码编程。之前都是针对具体的类型进行编程。 模板分为函数模板和类模板。 函数模板 当我们想要使用一个swap可以用作多种类型时&#xff0c;可以使用模板。这样我们就可以不使用重载&#xff0c;不…

商城小程序踩坑(一):iPhone 11、iPhoneX 等设备底部安全区域/小黑条适配

一、前言 这两天正在开发商城小程序-商品详情页&#xff0c;在做设备测试的时候突然发现详情页底部—— 购物车 和 购买区域在苹果手机上不适配&#xff0c;并且还存在小黑条。 底部功能没有办法正常使用。 如下图所示&#xff1a; 解决后效果&#xff0c;如下图所示&#xff…

Swagger之Hello World !

目录 ■1&#xff0e;前言・Swagger介绍 ■2&#xff0e;例子&#xff0c;如果基于Spring Boot项目&#xff0c;实现Swagger---非常简单 2&#xff0e;1&#xff0e;已有的SpringBoot项目 2&#xff0e;2&#xff0e;修改POM文件 2&#xff0e;3&#xff0e;添加Config文件…

html请求谷歌音频跨域问题(谷歌翻译接口)虚拟机ping不通google(下载谷歌音频、下载百度翻译音频)

文章目录 调用谷歌翻译接口&#xff0c;尝试了几种方案&#xff0c;都提示跨域不行第一种&#xff08;通过js代码获取音频文件的Blob对象&#xff0c;提示跨域了&#xff09;代码结果 第二种&#xff08;尝试新窗打开音频url&#xff0c;404&#xff0c;估计也是跨域了&#xf…

StarRocks Friends 广州站精彩回顾

上周六&#xff0c;StarRocks & Friends 活动在羊城广州成功举行&#xff0c;社区的小伙伴齐聚一堂&#xff0c;共同探讨了 StarRocks 在业界的应用实践和湖仓一体等热门话题。 本文总结了技术交流活动的关键内容和视频资料&#xff0c;感谢社区每一位小伙伴的支持和参与&…

如何提高接口测试覆盖率?

接口测试是测试系统组件间接口的一种测试。 接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。 测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。 接口测试该如何提高测试的覆盖率呢&#…

PCL点云处理之最小二乘空间直线拟合(3D) (二百零二)

PCL点云处理之最小二乘空间直线拟合(3D) (二百零二) 一、算法简介二、实现代码三、效果展示一、算法简介 对于空间中的这样一组点:大致呈直线分布,散乱分布在直线左右, 我们可采用最小二乘方法拟合直线,更进一步地,可以通过点到直线的投影,最终得到一组严格呈直线分布…

软件测试一周面试十家公司,分享面试经历

从开始面试讲起&#xff0c;公司规模我分成5类&#xff1a;创业公司0-20人&#xff0c;小型公司20-40人&#xff0c;中小型50-99&#xff0c;中型公司100-499即将上市的那种&#xff0c;已上市公司100-499。 创业公司 第一个面试的那家创业公司特别坑&#xff0c;开始面试&am…

4年测试“我“该何去何从?测试还是测试开发?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 4年测试&#xff…

秋招备战笔试Day2

目录 单选 1.A 派生出子类 B &#xff0c; B 派生出子类 C &#xff0c;并且在 java 源代码有如下声明&#xff1a; 2.下面代码将输出什么内容&#xff1a;&#xff08;&#xff09; 3.阅读如下代码。 请问&#xff0c;对语句行 test.hello(). 描述正确的有&#xff08;&…

vlan access, trunk, hybrid (tagged/untagged) 笔记

vlan 接口和配置 PVID&#xff08;port vlan ID&#xff09; 定义 pvid 主要目的&#xff1a; 当交换机接口收到没有 vlan tag 标签的包时&#xff0c;接口会将定义的 pvid 作为当前包的 vlan id。当对映 pvid vlan 的包&#xff0c;通过当前交换机接口发出时&#xff0c;接…

ADSelfService Plus:保护密码安全的最佳解决方案

密码安全是当今数字时代中至关重要的话题。随着互联网和信息技术的迅速发展&#xff0c;我们的生活变得越来越数字化&#xff0c;密码已成为我们生活中不可或缺的一部分。然而&#xff0c;随着各种网络威胁和黑客攻击不断增加&#xff0c;保护我们的密码变得越来越重要。 密码安…

测试工程师刚入职如何快速熟悉需求并输出测试用例?

刚入职第一天&#xff0c;早上办完入职&#xff0c;下午就就分配了测试任务&#xff0c;2个模块13条短信验证&#xff0c;2天内输出测试用例&#xff08;xmind输出功能点&#xff0c;excel书写业务流&#xff09;。测试负责人给我们快速讲了一下业务&#xff0c;在这过程中大概…

openssl/bn.h: No such file or directory

报错截图 解决方法 ubuntu apt install libssl-dev -y centos yum install openssl-devel -y

echarts实现多层环图(复制粘贴即可)

data里面参数配置&#xff1a; // 多重环图optionCircle: {tooltip: {show: false,trigger: item,formatter: "{a} : {c} ({d}%)"},color: [#3AB1EB, #D48B6A, #5B41C8, #FE7E02],legend: {orient: horizontal,itemWidth: 30, // 图例标记的图形宽度。itemHeight…

从产品和运营的角度聊聊,如何有效吸引与引导用户注册转化?

从产品和运营的角度聊聊 如何有效吸引与引导用户注册转化&#xff1f; 正文共&#xff1a;4360字 23图 预计阅读时间&#xff1a;11分钟 1 如何进行改版&#xff0c;找找思路&#xff1f; 前段时间在做公司的网站改版策划&#xff0c;此前接触的都是一些ToB的解决方案提供商…