c++ 不插入重复元素但也不排序_面试官爱问的 10 大经典排序算法,20+ 张图来搞定...

(给算法爱好者加星标,修炼编程内功)

作者:技术让梦想更伟大 / 李肖遥 (本文来自作者投稿)

冒泡排序

简介

冒泡排序是因为越小的元素会经由交换以升序或降序的方式慢慢到数列的顶端,就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名冒泡排序

复杂度与稳定性

c2edce333f11e7e77ad197e548ca049f.png

思路原理

以顺序为例

  1. 从第一个元素开始一个一个的比较相邻的元素,如果第一个比第二个大即a[1]>a[2],就彼此交换。

  2. 从第一对到最后一对,对每一对相邻元素做一样的操作。此时在最后的元素应该会是最大的数,我们也称呼一遍这样的操作一趟冒泡排序

  3. 针对所有的元素重复以上的步骤,每一趟得到的最大值已放在最后,下一次操作则不需要将此最大值纳入计算。

  4. 持续对每次对越来越少的元素,重复上面的步骤。

  5. 直到所有的数字都比较完成符合a[i],即完成冒泡排序。

图示过程

以数组数据{ 70,50,30,20,10,70,40,60}为例:

c77d31d1fc49a06c4dd5e5d54cbe1586.png

如图,每一次排序把一个最大的数被放在了最后,然后按照这个趋势逐渐往前,直到按从小到大的顺序依次排序。

到了第4轮的时候,整个数据已经排序结束了,但此时程序仍然在进行。

直到第5,6,7轮程序才算真正的结束,这其实是一种浪费算力的表现

主要代码实现

void bubble_sort(int a[],int n) {
    for(int i=0; i        for(int j=0; j            if(a[j]>a[j+1]) {
                swap(a[j],a[j+1]);  //交换数据
            }
        }
    }
}

注意,由于C++的namespace std命名空间的使用,std自带了交换函数swap(a,b),可以直接使用,其功能是交换a与b的两个值,当然你可以自定义swap函数,其模板代码为:

template        //模板类,可以让参数为任意类型
void swap(T &a,T &b) {
    T c(a);
    a=b;
    b=c;
}

或者指定类型修改为整形,如:

void swap(int &a, int &b) { //指定类型
    int temp = a;
    a = b;
    b = temp;
}

选择排序

简介

选择排序是一种简单直观的排序算法,它从待排序的数据元素中选出最小或最大的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小或最大元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

复杂度与稳定性

9ba11789c47be9148f49f9f77ff81040.png

过程介绍(以顺序为例)

  1. 首先设置两个记录i和j,i从数组第一个元素开始,j从(i+1)个元素开始。

  2. 接着j遍历整个数组,选出整个数组最小的值,并让这个最小的值和i的位置交换。

  3. i选中下一个元素(i++),重复进行每一趟选择排序。

  4. 持续上述步骤,使得i到达(n-1)处,即完成排序 。

图示过程:

以数据{2,10,9,4,8,1,6,5}为例

be78085d5107898bfdcd359b6d7120e0.png

如图所示,每次交换的数据使用红颜色标记出,已经排好序的数据使用蓝底标注,

每一趟从待排序的数据元素中选出最小的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。

我们只需要进行n-1趟排序即可,因为最后剩下的一个数据一定是整体数据中最大的数据。

代码实现

void select_sort(int a[],int n){
    int temp;
    for(int i=0;i        temp=i;      //利用一个中间变量temp来记录需要交换元素的位置
        for(int j=i+1;j            if(a[temp]>a[j]){   //选出待排数据中的最小值
                temp=j;  
            }
        }
        swap(a[i],a[temp]); //交换函数
    }

相比冒泡排序的不断交换,简单选择排序是等到合适的关键字出现后再进行交换,并且交换一次就可以达到一次冒泡的效果。

插入排序

简介

插入排序是一种最简单的排序方法,对于少量元素的排序,它是一个有效的算法。

复杂度与稳定性

8ab214b20e6b941055d2ce7364831690.png

过程介绍

首先将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。

每一步将一个待排序的元素,按其排序码的大小,插入到前面已经排好序的一组元素的适当位置上去,直到元素全部插入为止。

可以选择不同的方法在已经排好序数据表中寻找插入位置。根据查找方法不同,有多种插入排序方法,下面要介绍的是直接插入排序。

  1. 每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。

  2. 第一趟比较前两个数,然后把第二个数按大小插入到有序表中;

  3. 第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;

  4. 依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。

图示过程

以数组数据{ 70,50,30,20,10,70,40,60}为例:

d1880ad3b010cd2d12d0fe469ad4fcaf.png

将红色的数据依次插入组成一个逐渐有序的数组

代码实现

void insert_sort(int a[],int n) {
    int i,j;
    //外层循环标识并决定待比较的数值
    for(i=1; i        if(a[i]            int temp=a[i];
            //待比较数值确定其最终位置
            for(j=i-1; j>=0 && a[j]>temp; j--) {
                a[j+1]=a[j];
            }
            a[j+1]=temp;//此处就是a[j+1]=temp;
        }
    }
}

希尔排序

简介

希尔排序又称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。

希尔排序是非稳定排序算法,在对几乎已经排好序的数据操作时,效率极高,即可以达到线性排序的效率。

复杂度与稳定性

8da8ef4d45504322af5d91113c87a4c8.png

过程介绍

先将整个待排序的记录序列分组,对若干子序列分别进行直接插入排序,随着增量逐渐减少即整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

过程如下:

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

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

  3. 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。

  4. 仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

图示过程

78f7189e24d57350ab9a44b5e00e1f43.png

可以看见,相比直接插入排序由于可以每趟进行分段操作,故整体效率体现较高。

主要代码实现

void shellSort(int arr[], int n) {
    int i, j, gap;
    for (gap = n / 2; gap > 0; gap /= 2) {
        for (i = 0; i             for (j = i + gap; j                 for (int k = j; k > i && arr[k]                     swap(arr[k-gap], arr[k]);
                }
            }
        }
    }
}

堆排序

简介

堆排序是指利用堆这种数据结构所设计的一种排序算法,它是一个近似完全二叉树的结构。

同时堆满足堆积的性质:即子结点的键值或索引总是小于或大于它的父节点。

复杂度与稳定性

a4de7a60ce50c638cc5aae3cc7509922.png

什么是堆?

由于堆排序比较特殊,我们先了解一下堆是什么。

堆是一种非线性的数据结构,其实就是利用完全二叉树的结构来维护的一维数组,利用这种结构可以快速访问到需要的值,堆可以分为大顶堆和小顶堆。

  • 大顶堆:每个结点的值都大于或等于其左右孩子结点的值

  • 小顶堆:每个结点的值都小于或等于其左右孩子结点的值

过程介绍

首先把待排序的元素按照大小在二叉树位置上排列,且要满足堆的特性,如果根节点存放的是最大的数,则叫做大根堆,反之就叫做小根堆了。

根据这个特性就可以把根节点拿出来,然后再堆化下,即用父节点和他的孩子节点进行比较,取最大的孩子节点和其进行交换,再把根节点拿出来,一直循环到最后一个节点,就排序好了。

由于堆的实现图解需要很长篇幅,故这里不画图,肖遥会单独出一篇堆的图解,感谢关注。其代码实现如下。

主要代码实现

/* Function: 交换交换根节点和数组末尾元素的值*/
void Swap(int *heap, int len) {
    int temp;
  
    temp = heap[0];
    heap[0] = heap[len-1];
    heap[len-1] = temp;
}
  
/* Function: 构建大顶堆 */
void BuildMaxHeap(int *heap, int len) {
    int i,temp;
    for (i = len/2-1; i >= 0; i--) {
        if ((2*i+1)             temp = heap[i];
            heap[i] = heap[2*i+1];
            heap[2*i+1] = temp;
            /* 检查交换后的左子树是否满足大顶堆性质 如果不满足 则重新调整子树结构 */
            if ((2*(2*i+1)+1                 BuildMaxHeap(heap, len);
            }
        }
        if ((2*i+2)             temp = heap[i];
            heap[i] = heap[2*i+2];
            heap[2*i+2] = temp;
            /* 检查交换后的右子树是否满足大顶堆性质 如果不满足 则重新调整子树结构 */
            if ((2*(2*i+2)+1                 BuildMaxHeap(heap, len);
            }
        }
    }
}

归并排序

简介

归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法的一个非常典型的应用,其核心思想是将两个有序的数列合并成一个大的有序的序列。

复杂度与稳定性

34784780a4bb68061cb127c2d638f6c6.png

注:归并排序需要创建一个与原数组相同长度的数组来辅助排序

过程介绍

首先将已有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,再使子序列段间有序。

过程如下:

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置

  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

  4. 重复步骤c直到某一指针超出序列尾

  5. 将另一序列剩下的所有元素直接复制到合并序列尾

图示过程

第一次排序将数据分为“两个”一组,组内顺序,其次再逐个的将各组进行整合,最终完成归并排序

bb44ba6af8acba912d1fffb84649a5ee.png

主要代码实现

void merge(int arr[],int l,int mid,int r) {
    int aux[r-l+1];//开辟一个新的数组,将原数组映射进去
    for(int m=l; m<=r; m++) {
        aux[m-l]=arr[m];
    }
  
    int i=l,j=mid+1;//i和j分别指向两个子数组开头部分
  
    for(int k=l; k<=r; k++) {
        if(i>mid) {
            arr[k]=aux[j-l];
            j++;
        } else if(j>r) {
            arr[k]=aux[i-l];
            i++;
        } else if(aux[i-l]-l]) {
            arr[k]=aux[i-l];
            i++;
        } else {
            arr[k]=aux[j-l];
            j++;
        }
    }
}
void merge_sort(int arr[],int n) {for(int sz=1; sz<=n; sz+=sz) {for(int i=0; i+sz            //对局部:arr[i...sz-1]和arr[i+sz.....i+2*sz-1]进行排序
            merge(arr,i,i+sz-1,min(i+sz+sz-1,n-1));    //min函数防止越界
        }
    }
}

快速排序

简介

快速排序在1960年提出,是考察次数最多的排序,无论是在大学专业课的期末考试,还是在公司的面试测试题目中,快速排序都极大的被使用,在实际中快速排序也极大的被使用。

复杂度与稳定性

2cb3d8a043bd534b67dffb4fc9e4631b.png

过程介绍

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

  1. 在数组中选择一个基准点

  2. 分别从数组的两端扫描数组,设两个指示标志

  3. 从后半部分开始,如果发现有元素比该基准点的值小,就交换位置

  4. 然后从前半部分开始扫描,发现有元素大于基准点的值,继续交换位置

  5. 如此往复循环,然后把基准点的值放到high这个位置,排序完成

以后采用递归的方式分别对前半部分和后半部分排序,当前半部分和后半部分均有序时该数组就自然有序了。

图示过程

可以看出,在第四趟时已经达到顺序,但是仍然还是会继续计算几趟直到完成全部运算

c74e268af0cef405c77250d86fbc566c.png

主要代码实现

void qucik_sort(int a[],int low,int high) {
  int i,j,temp;
  i=low;
  j=high;
  if(low    temp=a[low];    //设置枢轴
    while(i!=j) {
      while(j>i&&a[j]>=temp) {
        --j;
      }
      if(i        a[i]=a[j];
        ++i;
      }

      while(i        ++i;
      }
      if(i        a[j]=a[i];
        --j;
      }
    }
    a[i]=temp;
    qucik_sort(a,low,i-1);
    qucik_sort(a,i+1,high);
  }
}

计数排序

简介

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

计数排序算法不是基于元素比较,而是利用数组下标来确定元素的正确位置。

它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k),快于任何比较排序算法。

当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序。

复杂度与稳定性

d64c9d5afe9b9a8ca536cd999894a1f9.png

过程介绍

  1. 找出待排序的数组中最大和最小的元素

  2. 统计数组中每个值为i的元素出现的次数,存入数组C的第i项

  3. 对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)

  4. 反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1

图示过程

如下图,A为待排序的数组,C记录A中各个值的数目。

66a1322872ad063c85f9bb265c352acf.png

将C[i]转换为值小于等于i的元素个数。

a10af456270bece96d188eac4f242206.png

为数组A从后向前的每个元素找到对应的B中的位置,每次从A中复制一个元素到B中,C中相应的计数减一。

faeb561531dd117b110bbfda7d600c51.png

当A中的元素都复制到B中后,B就是排序好的结果,如图所示。3a9d9f49eba4caab37c0de3b2245364d.png

代码实现

#include
#include
#include

void CountSort(int *arr, int len){
    if(arr == NULL) return;
    int max = arr[0], min = arr[0];
    for(int i = 1; i         if(arr[i] > max)    max = arr[i];
        if(arr[i]     }
    int size = max - min + 1;
    int *count =(int*)malloc(sizeof(int)*size);
    memset(count, 0, sizeof(int)*size);

    for(int i = 0; i         count[arr[i] - min]++;//包含了自己!
    for(int i = 1; i         count[i] += count[i - 1];

    int* psort =(int*)malloc(sizeof(int)*len);
    memset(psort, 0, sizeof(int)*len);

    for(int i = len - 1; i >= 0; i--){
        count[arr[i] - min]--;//要先把自己减去
        psort[count[arr[i] - min]] = arr[i];
    }

    for(int i = 0; i         arr[i] = psort[i];
    }

    free(count);
    free(psort);
    count = NULL;
    psort = NULL;
}


void print_array(int *arr, int len)
{
    for(int i=0; i        printf("%d ", arr[i]);
    printf("\n");
}

int main()
{
    int arr[8] = {2, 5, 3, 0, 2, 3, 0, 3};
    CountSort(arr, 8);
    print_array(arr, 8);

    return 0;
}

桶式排序

简介

桶排序也称箱排序,原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。

桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。

复杂度与稳定性

90c6d5ec1bf53883d24ed1969655a2b5.png

过程介绍

  1. 根据待排序集合中最大元素和最小元素的差值范围和映射规则,确定申请的桶个数;

  2. 遍历待排序集合,将每一个元素移动到对应的桶中;

  3. 对每一个桶中元素进行排序,并移动到已排序集合中。

图示过程

元素分布在桶中:

d2e228afe3850ad1f54a7c4f66519f21.png

然后,元素在每个桶中排序:

5d345e9cb628207e9d96e15a984351c1.png

代码实现

#include
#include
#include
using namespace std;
const int BUCKET_NUM = 10;

struct ListNode{
    explicit ListNode(int i=0):mData(i),mNext(NULL){}
    ListNode* mNext;
    int mData;
};

ListNode* insert(ListNode* head,int val){
    ListNode dummyNode;
    ListNode *newNode = new ListNode(val);
    ListNode *pre,*curr;
    dummyNode.mNext = head;
    pre = &dummyNode;
    curr = head;
    while(NULL!=curr && curr->mData<=val){
            pre = curr;
            curr = curr->mNext;
    }
    newNode->mNext = curr;
    pre->mNext = newNode;
    return dummyNode.mNext;
}


ListNode* Merge(ListNode *head1,ListNode *head2){
    ListNode dummyNode;
    ListNode *dummy = &dummyNode;
    while(NULL!=head1 && NULL!=head2){
            if(head1->mData <= head2->mData){
                    dummy->mNext = head1;
                    head1 = head1->mNext;
            }else{
                    dummy->mNext = head2;
                    head2 = head2->mNext;
            }
            dummy = dummy->mNext;
    }
    if(NULL!=head1) dummy->mNext = head1;
    if(NULL!=head2) dummy->mNext = head2;

    return dummyNode.mNext;
}

void BucketSort(int n,int arr[]){
    vector buckets(BUCKET_NUM,(ListNode*)(0));for(int i=0;i            int index = arr[i]/BUCKET_NUM;
            ListNode *head = buckets.at(index);
            buckets.at(index) = insert(head,arr[i]);
    }
    ListNode *head = buckets.at(0);for(int i=1;i            head = Merge(head,buckets.at(i));
    }for(int i=0;i            arr[i] = head->mData;
            head = head->mNext;
    }
}

基数排序

简介

基数排序是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,在某些时候,基数排序法的效率高于其它的稳定性排序法。

复杂度与稳定性

dd12bfd3a0bce4aefcf5d01a65fdafb4.png

图示过程

设有一个初始序列为: R {50, 123, 543, 187, 49, 30, 0, 2, 11, 100}

ef93f4523b1e5576f8e8bf8b3d833ea3.png

过程介绍

任何一个阿拉伯数,它的各个位数上的基数都是以0~9来表示的。所以我们不妨把0~9视为10个桶。

  1. 我们先根据序列的个位数的数字来进行分类,将其分到指定的桶中。

  2. 分类后,我们在从各个桶中,将这些数按照从编号0到编号9的顺序依次将所有数取出来。

  3. 得到的序列就是个位数上呈递增趋势的序列。

  4. 按照上图个位数排序:{50, 30, 0, 100, 11, 2, 123, 543, 187, 49}

  5. 接下来对十位数、百位数也按照这种方法进行排序,最后就能得到排序完成的序列。

主要代码实现

public class RadixSort {
    // 获取x这个数的d位数上的数字
    // 比如获取123的1位数,结果返回3
    public int getDigit(int x, int d) {
        int a[] = {1, 1, 10, 100}; // 本实例中的最大数是百位数,所以只要到100就可以了
        return ((x / a[d]) % 10);
    }

  public void radixSort(int[] list, int begin, int end, int digit) {
      final int radix = 10; // 基数
      int i = 0, j = 0;
      int[] count = new int[radix]; // 存放各个桶的数据统计个数
      int[] bucket = new int[end - begin + 1];
      // 按照从低位到高位的顺序执行排序过程
      for (int d = 1; d <= digit; d++) {
          // 置空各个桶的数据统计
          for (i = 0; i               count[i] = 0;
          }
          // 统计各个桶将要装入的数据个数
          for (i = begin; i <= end; i++) {
              j = getDigit(list[i], d);
              count[j]++;
          }
          // count[i]表示第i个桶的右边界索引
          for (i = 1; i               count[i] = count[i] + count[i - 1];
          }
          // 将数据依次装入桶中
          // 这里要从右向左扫描,保证排序稳定性
          for (i = end; i >= begin; i--) {
              j = getDigit(list[i], d);
              // 求出关键码的第k位的数字, 例如:576的第3位是5
              bucket[count[j] - 1] = list[i];
              // 放入对应的桶中,count[j]-1是第j个桶的右边界索引
              count[j]--; // 对应桶的装入数据索引减一
          }
          // 将已分配好的桶中数据再倒出来,此时已是对应当前位数有序的表
          for (i = begin, j = 0; i <= end; i++, j++) {
              list[i] = bucket[j];
          }
      }
  }

  public int[] sort(int[] list) {
      radixSort(list, 0, list.length - 1, 3);
      return list;
  }

  // 打印完整序列
  public void printAll(int[] list) {
      for (int value : list) {
          System.out.print(value + "\t");
      }
      System.out.println();
  }

  public static void main(String[] args) {
      int[] array = {50, 123, 543, 187, 49, 30, 0, 2, 11, 100};
      RadixSort radix = new RadixSort();
      System.out.print("排序前:\t\t");
      radix.printAll(array);
      radix.sort(array);
      System.out.print("排序后:\t\t");
      radix.printAll(array);
  }
}

总结

10种排序算法对比,我们了解到了各种排序的原理及优缺点,记住任何一种排序都不是十全十美的,因此在我们实际应用中,最好的方式就是扬长避短。

- EOF -

推荐阅读  点击标题可跳转

1、图解排序算法:归并排序

2、图解排序算法:快速排序

3、深入理解快速排序和 STL 的 sort 算法

觉得本文有帮助?请分享给更多人

关注「算法爱好者」加星标,修炼编程内功

e437d74fecb2457fde969d4cf5a6ac58.png

点赞和在看就是最大的支持❤️

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

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

相关文章

计算机硬件操作系统应用软件之间的关系,操作系统是其他应用软件运行的基础,什么是操作系统...

简单理解操作系统就是一个人与计算机硬件之间的中介。打个比喻&#xff0c;没有操作系统的机器就像是没有用的砖头一样&#xff0c;而有操作系统的机器就是可以玩的砖头。 (推荐学习&#xff1a;phpstorm)操作系统&#xff0c;英文名称Operating System&#xff0c;简称OS&…

matplotlib 横坐标少了一个点_收藏起来!比 matplotlib 效率高十倍的数据可视化神器!...

点击上方“涛哥聊Python”&#xff0c;选择“星标”公众号作者&#xff1a;Will Koehrsen图文投稿&#xff1a;Allen编辑&#xff1a;Kooyee原文链接&#xff1a;https://towardsdatascience.com/the-next-level-of-data-visualization-in-python-dd6e99039d5e其他&#xff1a;…

ssd训练自己数据集

1、用labelImg标数据 2、将数据转换为tfrecord 错误记录&#xff1a; NotFoundError&#xff1a;无法创建NewWriteableFile 解决方法&#xff1a;您需要在运行此脚本的运行环境文件夹中自己创建一个目录 1、前期准备工作 第一步&#xff1a;先将SSD框架下载到本地&#…

elasticsearch date_MySQL数据实时增量同步到Elasticsearch

Mysql到Elasticsearch的数据同步&#xff0c;一般用ETL来实现&#xff0c;但性能并不理想&#xff0c;目前大部分的ETL是定时查询Mysql数据库有没有新增数据或者修改数据&#xff0c;如果数据量小影响不大&#xff0c;但如果几百万上千万的数据量性能就明显的下降很多&#xff…

联想计算机不能进入系统桌面,联想笔记本进不去桌面的解决方法

联想笔记本进不去桌面的解决方法笔记本电脑开机后&#xff0c;电源指示灯亮&#xff0c;显示器屏如果有显示&#xff0c;但进不了系统&#xff0c;这种情况多数是系统故障导致的&#xff0c;可以尝试开机按F8键&#xff0c;进入安全模式&#xff0c;然后进入最后一次安全配置进…

win10 make命令的安装

1、下载MinGWMinGW官网下载&#xff1a;http://www.mingw.org &#xff0c;点击右上角Downloads 或者网盘下载&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1vQVKycK1TKVsnLV_OMgiCg 提取码&#xff1a;bbhl 点击下载 mingw-get-setup.exe 安装 mingw-get-setup.exe…

html中svg的css,HTML5 内联 SVG

什么是SVG&#xff1f;SVG 指可伸缩矢量图形 (Scalable Vector Graphics)SVG 用于定义用于网络的基于矢量的图形SVG 使用 XML 格式定义图形SVG 图像在放大或改变尺寸的情况下其图形质量不会有损失SVG 是万维网联盟的标准SVG 的优势与其他图像格式相比(比如 JPEG 和 GIF)&#x…

fast-rcnn win10 tensorflow部署

1、下载代码https://github.com/chde222/Faster-RCNN-TensorFlow-Python3 2、安装所依赖包 pip install -r requirements.txt 或者单独利用pip install cython pip install easydict 3、在 ./data/coco/pythonAPI 下打开cmd运行&#xff1a; python setup.py build_ext --in…

vue 获取url地址的参数_Vue之vuerouter的使用

1. 什么是vue-router?所谓的vue-router, 通俗的来讲 就是路由 但是这个和后端路由是不同的, 这是前端路由,是url和单页面组件的对应关系, 也就是SPA(单页应用)的路径管理器。再通俗的说&#xff0c;vue-router就是WebApp的链接路径管理系统。vue-router是Vue.js官方的路由插件…

win10下openpose1.5安装

历经一个星期的安装挫折&#xff0c;终于安装成功了。赶紧记录一下。 1、准备所需资料 &#xff08;1&#xff09;下载cuda和cudnn。版本最好都是cuda10和cudnn10.我下载的是下图所示版本。 如果不是这个版本可能会出错&#xff0c;而且出错几率很高。本人就因为安装的cuda10…

div展示html文本,html – 使文本适合div

我一直在努力重新创建我在90年代创建的父亲网站(呃),我一直无法让文本适合div内部并水平对齐.我需要将文本放在一起,以便它们适合div.这是jsfiddle中页面的代码示例HTMLHomeInside StaffOur Mission示例CSSdiv img#header{width: 50%;height: 15%;margin-left: 125px;margin-ri…

ImportError: cannot import name 'pyopenpose' from 'openpose'错误解决方法

前提条件&#xff1a;openpose1.5配置过程前面都成功&#xff0c;c api成功运行&#xff0c;但是python api配置中&#xff0c;cmake也添加了build_python_path.运行中仍出现 ImportError: cannot import name pyopenpose from openpose 这个错误。 解决方法&#xff1a; 将你…

python语句join_详解Python中的join()函数的用法

原博文 2017-08-07 20:51 − 函数&#xff1a;string.join() Python中有join()和os.path.join()两个函数&#xff0c;具体作用如下&#xff1a; join()&#xff1a; 连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串 &n...0584 相…

python glob.glob使用

函数功能&#xff1a;匹配所有的符合条件的文件&#xff0c;并将其以list的形式返回 示例&#xff1a; 当前文件夹下有如下文件 import globlist glob.glob(‘*g’)print(list) 结果&#xff1a; [dog.1012.jpg, dog.1013.jpg, dog.1014.jpg, dog.1015.jpg, dog.1016.jpg]

nohup启动jar_nohup命令详解

nohup命令详解在我们想要把SpringBoot微服务工程部署到远程服务器时&#xff0c;会通过java -jar springboot.jar的方式启动SpringBoot微服务。但是当我们把运行这个命令的SSH客户端退出登录就会导致SpringBoot进程也一起停止了&#xff0c;然后当然就没法访问我们启动的项目了…

python用pip安装pygame_安装pygame和pip的问题以及过程

1. 先安装pip(一个重要的工具cnqqtd) 2. 安装与python版和系统本相匹配的pygame 详细安装过程 Pip请到这里安装 https://pypi.python.org/pypi/pip#download 下载完成后,会获得一个叫git-pip.py的文件 • 打开git-pip.py文件存在的目录,按下shift rightClick • 打开windows Po…

.net fileupload批量上传可删除_【JavaWeb基础】文件上传和下载(修订版)

前言只有光头才能变强。文本已收录至我的GitHub仓库&#xff0c;欢迎Star&#xff1a;https://github.com/ZhongFuCheng3y/3y什么是文件上传&#xff1f;文件上传就是把用户的信息保存起来。为什么需要文件上传&#xff1f;在用户注册的时候&#xff0c;可能需要用户提交照片。…

object detection之Win10配置

1、下载models。 https://github.com/tensorflow/models 并文件解压。 2、下载protos文件 https://github.com/protocolbuffers/protobuf/releases?afterv3.9.1 我这里下载的3.7.0版本。注意一定要下载protoc-xxx-win64.zip版本。必须是带有win64的压缩包&#xff0c;否则可…

idea卸载不干净怎么办_fxfactory卸载不干净?Fxfactory及插件卸载教程

fxfactory卸载不干净怎么办&#xff1f;fxfactory是一款非常受欢迎的视频特效插件合集&#xff0c;能应用到FCPX、AE、PR、motion等软件中。过多特效插件下载会导致这些软件运行打开速度慢&#xff0c;那么如何卸载fxfactory这款软件或者删除那些特效插件呢&#xff1f;跟随小编…

矩阵标准型的系数是特征值吗_「线性代数」根据特征值,将二次型化为标准形、规范形...

今天我们来聊一聊线性代数中的二次型化为规范形、标准形的内容&#xff0c;这块知识相当重要&#xff0c;我看了看&#xff0c;几乎每一年的考研数学中都会涉及到一道关于这个知识点的题目&#xff0c;这次的整理&#xff0c;不仅帮助大家整理清楚思路&#xff0c;也是为自己整…