数据结构:10、排序

本文将会介绍8种排序,并在文章末附上代码

一、排序的概念

排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次
序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排
序算法是稳定的;否则称为不稳定的。
内部排序:数据元素全部放在内存中的排序。
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

二、排序的实现

1、直接插入排序

直接插入排序就是判断这个数是否比前面的数小,如果小就放在这个地方,然后一趟一趟的,他的排序在越接近有序就越快,代码和测试结果如下。

void InsertSort(int* a, int n)
{for (int i = 1; i < n; i++){int end = i - 1;int tmp = a[i];while (end>=0){if (a[end] > tmp){a[end + 1] = a[end];end--;}else{break;}}a[end + 1] = tmp;}
}

2、希尔排序

希尔排序就是一个叫希尔的大佬发明出来的,既然直接插入排序越接近有序就越快,那么给他划分成一块一块,对每一块进行排序,然后在进行总体排序,代码和测试结果如下。

void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;  for (int i = 0; i < n - gap; ++i){int end = i;int tmp = a[end + gap];while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}

3、选择排序

这个选择排序的原理就是选出这组数据的最大或者最小插在最前或者最后,听起来就很慢,所以这里进行了一点点优化,一下排序两个数据,但是依然还是很慢很拉跨,在文章末进行所有测试的比较时可以看出,代码与测试结果如下。

void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void SelectSort(int* a, int n)
{int begin = 0, end = n - 1;while (begin < end){int maxi = begin, mini = begin;for (int i = begin; i <= end; i++){if (a[i] > a[maxi]){maxi = i;}if (a[i] < a[mini]){mini = i;}}Swap(&a[begin], &a[mini]);if (begin == maxi){maxi = mini;}Swap(&a[end], &a[maxi]);++begin;--end;}
}

4、堆排序

堆排序首先就是建堆,这里是升序所以就是建大堆,当建堆完成后,交换首尾两个数然后进行调整,这个就是堆排序,代码以及测试结果如下。

void AdjustDown(int* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child + 1] > a[child]){++child;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}void HeapSort(int* a, int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);}int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}

5、冒泡排序

冒泡排序,肯定都不陌生,我接触的第一个排序就是他,之前一直认为他最好用,直到接触了本文的其他排序,瞬间不香了,他的原理就是每一趟都依次进行比较交换,代码与测试结果如下。

void BubbleSort(int* a, int n)
{for (int j = 0; j < n; ++j){bool exchange = false;for (int i = 1; i < n - j; i++){if (a[i - 1] > a[i]){int tmp = a[i];a[i] = a[i - 1];a[i - 1] = tmp;exchange = true;}}if (exchange == false){break;}}
}

6、快速排序

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

有三种划分方式,第一种也是他本人发明的,就是选一个做为key然后左边找比key小的数右边找比key大数,找了停止,然后交换左右两边,直到两边相遇,再把相遇的值和key交换,这样就完成了一次排序,就会形成key左边的比key小,右边的比key大。

第二种就是挖坑法,把key的值保存在临时变量里面,然后形成一个坑,然后右边大的左找到比他的小放到坑里,在找到的地方形成一个坑,左边在走找到大的放到坑里,在挖个坑,直到遇到然后把key放到相遇的这个坑里。

第三种就是前后指针的方法,就是prev每次都需要指向从左到它本身之间最后一个小于基准值的数,如果cur的值大于基准值,这时只让cur++,如果cur指向的位置小于基准值,这时我们让prev++后,判断是否与cur的位置相等,若不相等,则交换cur和prev的值。直到cur>end后,我们再交换prev和基准值,这样基准值的位置也就确定了。

普通的递归快排结束了,就是利用栈中进行排序的方式,方法和上面一样,就是把数据的存储利用栈进行压入与取出,代码与测试结果如下。

int GetMidIndex(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[left] < a[right]){return right;}else{return left;}}else {if (a[mid] > a[right]){return mid;}else if (a[left] > a[right]){return right;}else{return left;}}
}int PartSort1(int* a, int left, int right)
{int midi = GetMidIndex(a, left, right);Swap(&a[left], &a[midi]);int keyi = left;while (left < right){while (left < right && a[right] >= a[keyi]){--right;}while (left < right && a[left] <= a[keyi]){++left;}Swap(&a[left], &a[right]);}Swap(&a[keyi], &a[left]);return left;
}int PartSort2(int* a, int left, int right)
{int midi = GetMidIndex(a, left, right);Swap(&a[left], &a[midi]);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;}a[hole] = key;return hole;
}int PartSort3(int* a, int left, int right)
{int midi = GetMidIndex(a, left, right);Swap(&a[left], &a[midi]);int prev = left;int cur = left + 1;int keyi = left;while (cur <= right){if (a[cur] < a[keyi] && ++prev != cur){Swap(&a[prev], &a[cur]);}++cur;}Swap(&a[prev], &a[keyi]);keyi = prev;return keyi;
}void QuickSort(int* a, int begin, int end)
{if (begin >= end)return;int keyi = PartSort3(a, begin, end);QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
}void QuickSortNonR(int* a, int begin, int end)
{ST st;StackInit(&st);StackPush(&st, end);StackPush(&st, begin);while (!StackEmpty(&st)){int left = StackTop(&st);StackPop(&st);int right = StackTop(&st);StackPop(&st);int keyi = PartSort1(a, left, right);if (keyi + 1 < right){StackPush(&st, right);StackPush(&st, keyi + 1);}if (left < keyi - 1){StackPush(&st, keyi - 1);StackPush(&st, left);}}StackDestroy(&st);
}

7、归并排序

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤就是分解合并,不过在合并时要注意边界的问题,代码实现与测试结果如下。

void MergeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);_MergeSort(a, 0, n - 1, tmp);free(tmp);
}void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);int gap = 1;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;//printf("[%d,%d][%d,%d]\n", begin1, end1, begin2, end2);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));}//printf("\n");gap *= 2;}free(tmp);
}

8、计数排序

计数排序的原理就是统计相同元素出现次数,根据统计的结果将序列回收到原来的序列中,他的排序很快, 计数排序在数据范围集中时,效率很高,但是适用范围及场景有限,代码与测试结果如下。

void CountSort(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* countA = (int*)malloc(sizeof(int) * range);memset(countA, 0, sizeof(int) * range);for (int i = 0; i < n; i++){countA[a[i] - min]++;}int k = 0;for (int j = 0; j < range; j++){while (countA[j]--){a[k++] = j + min;}}
}

9、排序的稳定以及时间复杂度

排序方法平均情况最好情况最坏情况辅助空间稳定性
冒泡排序O(n^2)O(n)O(n^2)O(1)稳定
选择排序O(n^2)O(N^2)O(n^2)O(1)不稳定
直接插入排序O(n^2)O(n)O(n^2)O(1)稳定
希尔排序O(n*longn)~O(n^2)O(n^1.3)O(n^2)O(1)不稳定
堆排序O(n*longn)O(n*longn)O(n*longn)O(1)不稳定
归并排序O(n*longn)O(n*longn)O(n*longn)O(n)稳定
快速排序O(n*longn)O(n*longn)O(n^2)O(logn)~O(n)不稳定

三、代码

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Sort.h"
#include <time.h>void TestInsertSort()
{int a[] = { 9,5,3,4,1,5,3,6,1,2 };PrintfArry(a, sizeof(a) / sizeof(int));InsertSort(a, sizeof(a) / sizeof(int));PrintfArry(a, sizeof(a) / sizeof(int));
}void TestShellSort()
{int a[] = { 9,5,3,4,1,5,3,6,1,2 };PrintfArry(a, sizeof(a) / sizeof(int));ShellSort(a, sizeof(a) / sizeof(int));PrintfArry(a, sizeof(a) / sizeof(int));
}void TestBubbleSort()
{int a[] = { 9,5,3,4,1,5,3,6,1,2 };PrintfArry(a, sizeof(a) / sizeof(int));BubbleSort(a, sizeof(a) / sizeof(int));PrintfArry(a, sizeof(a) / sizeof(int));
}void TestSelectSort()
{int a[] = { 9,5,3,4,1,5,3,6,1,2 };PrintfArry(a, sizeof(a) / sizeof(int));SelectSort(a, sizeof(a) / sizeof(int));PrintfArry(a, sizeof(a) / sizeof(int));
}void TestHeapSort()
{int a[] = { 9,5,3,4,1,5,3,6,1,2 };PrintfArry(a, sizeof(a) / sizeof(int));HeapSort(a, sizeof(a) / sizeof(int));PrintfArry(a, sizeof(a) / sizeof(int));
}void TestQuickSort()
{int a[] = { 9,5,3,4,1,5,3,6,1,2 };PrintfArry(a, sizeof(a) / sizeof(int));//QuickSort(a, 0, sizeof(a) / sizeof(int) - 1);QuickSortNonR(a, 0, sizeof(a) / sizeof(int) - 1);PrintfArry(a, sizeof(a) / sizeof(int));
}void TestMergeSort()
{int a[] = { 9,5,3,4,1,5,3,6,1,2 };PrintfArry(a, sizeof(a) / sizeof(int));//MergeSort(a, sizeof(a) / sizeof(int));MergeSortNonR(a, sizeof(a) / sizeof(int));PrintfArry(a, sizeof(a) / sizeof(int));
}void TestCountSort()
{int a[] = { 9,5,3,4,1,5,3,6,1,2 };PrintfArry(a, sizeof(a) / sizeof(int));CountSort(a, sizeof(a) / sizeof(int));PrintfArry(a, sizeof(a) / sizeof(int));
}void TestOP()
{srand(time(0));const int N = 100000;int* a1 = (int*)malloc(sizeof(int) * N);int* a2 = (int*)malloc(sizeof(int) * N);int* a3 = (int*)malloc(sizeof(int) * N);int* a4 = (int*)malloc(sizeof(int) * N);int* a5 = (int*)malloc(sizeof(int) * N);int* a6 = (int*)malloc(sizeof(int) * N);int* a7 = (int*)malloc(sizeof(int) * N);int* a8 = (int*)malloc(sizeof(int) * N);for (int i = 0; i < N; ++i){a1[i] = rand();a2[i] = a1[i];a3[i] = a1[i];a4[i] = a1[i];a5[i] = a1[i];a6[i] = a1[i];a7[i] = a1[i];a8[i] = a1[i];}int begin1 = clock();InsertSort(a1, N);int end1 = clock();int begin2 = clock();ShellSort(a2, N);int end2 = clock();int begin3 = clock();BubbleSort(a3, N);int end3 = clock();int begin4 = clock();SelectSort(a4, N);int end4 = clock();int begin5 = clock();HeapSort(a5, N);int end5 = clock();int begin6 = clock();QuickSort(a6, 0, N - 1);int end6 = clock();int begin7 = clock();MergeSort(a7, N);int end7 = clock();int begin8 = clock();CountSort(a8, N);int end8 = clock();printf("InsertSort:%d\n", end1 - begin1);printf("ShellSort:%d\n", end2 - begin2);printf("BubbleSort:%d\n", end3 - begin3);printf("SelcetSort:%d\n", end4 - begin4);printf("HeapSort:%d\n", end5 - begin5);printf("QuickSort:%d\n", end6 - begin6);printf("MergeSort:%d\n", end7 - begin7);printf("CountSort:%d\n", end8 - begin8);free(a1);free(a2);free(a3);free(a4);free(a5);free(a6);free(a7);free(a8);
}int main()
{//TestInsertSort();//TestShellSort();//TestBubbleSort();//TestSelectSort();//TestHeapSort();//TestQuickSort();//TestMergeSort();//TestCountSort();TestOP();return 0;
}

Sort.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Sort.h"
#include "ST.h"
void PrintfArry(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");
}void InsertSort(int* a, int n)
{for (int i = 1; i < n; i++){int end = i - 1;int tmp = a[i];while (end>=0){if (a[end] > tmp){a[end + 1] = a[end];end--;}else{break;}}a[end + 1] = tmp;}
}void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;  for (int i = 0; i < n - gap; ++i){int end = i;int tmp = a[end + gap];while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}void BubbleSort(int* a, int n)
{for (int j = 0; j < n; ++j){bool exchange = false;for (int i = 1; i < n - j; i++){if (a[i - 1] > a[i]){int tmp = a[i];a[i] = a[i - 1];a[i - 1] = tmp;exchange = true;}}if (exchange == false){break;}}
}void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void SelectSort(int* a, int n)
{int begin = 0, end = n - 1;while (begin < end){int maxi = begin, mini = begin;for (int i = begin; i <= end; i++){if (a[i] > a[maxi]){maxi = i;}if (a[i] < a[mini]){mini = i;}}Swap(&a[begin], &a[mini]);if (begin == maxi){maxi = mini;}Swap(&a[end], &a[maxi]);++begin;--end;}
}void AdjustDown(int* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child + 1] > a[child]){++child;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}void HeapSort(int* a, int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);}int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}int GetMidIndex(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[left] < a[right]){return right;}else{return left;}}else {if (a[mid] > a[right]){return mid;}else if (a[left] > a[right]){return right;}else{return left;}}
}int PartSort1(int* a, int left, int right)
{int midi = GetMidIndex(a, left, right);Swap(&a[left], &a[midi]);int keyi = left;while (left < right){while (left < right && a[right] >= a[keyi]){--right;}while (left < right && a[left] <= a[keyi]){++left;}Swap(&a[left], &a[right]);}Swap(&a[keyi], &a[left]);return left;
}int PartSort2(int* a, int left, int right)
{int midi = GetMidIndex(a, left, right);Swap(&a[left], &a[midi]);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;}a[hole] = key;return hole;
}int PartSort3(int* a, int left, int right)
{int midi = GetMidIndex(a, left, right);Swap(&a[left], &a[midi]);int prev = left;int cur = left + 1;int keyi = left;while (cur <= right){if (a[cur] < a[keyi] && ++prev != cur){Swap(&a[prev], &a[cur]);}++cur;}Swap(&a[prev], &a[keyi]);keyi = prev;return keyi;
}void QuickSort(int* a, int begin, int end)
{if (begin >= end)return;int keyi = PartSort3(a, begin, end);QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
}void QuickSortNonR(int* a, int begin, int end)
{ST st;StackInit(&st);StackPush(&st, end);StackPush(&st, begin);while (!StackEmpty(&st)){int left = StackTop(&st);StackPop(&st);int right = StackTop(&st);StackPop(&st);int keyi = PartSort1(a, left, right);if (keyi + 1 < right){StackPush(&st, right);StackPush(&st, keyi + 1);}if (left < keyi - 1){StackPush(&st, keyi - 1);StackPush(&st, left);}}StackDestroy(&st);
}void _MergeSort(int* a, int begin, int end, int* tmp)
{if (begin == end)return;int mid = (begin + end) / 2;_MergeSort(a, begin, mid, tmp);_MergeSort(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 MergeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);_MergeSort(a, 0, n - 1, tmp);free(tmp);
}void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);int gap = 1;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;//printf("[%d,%d][%d,%d]\n", begin1, end1, begin2, end2);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));}//printf("\n");gap *= 2;}free(tmp);
}void CountSort(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* countA = (int*)malloc(sizeof(int) * range);memset(countA, 0, sizeof(int) * range);for (int i = 0; i < n; i++){countA[a[i] - min]++;}int k = 0;for (int j = 0; j < range; j++){while (countA[j]--){a[k++] = j + min;}}
}

Sort.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
void InsertSort(int* a,int n);
void PrintfArry(int* a, int n);
void ShellSort(int* a, int n);
void BubbleSort(int* a, int n);
void Swap(int* p1, int* p2);
void SelectSort(int* a, int n);
void AdjustDown(int* a, int n, int parent);
void HeapSort(int* a, int n);
void QuickSort(int* a, int begin, int end);
int PartSort1(int* a, int left, int right);
int PartSort2(int* a, int left, int right);
int PartSort3(int* a, int left, int right);
void QuickSortNonR(int* a, int begin, int end);
void _MergeSort(int* a, int begin, int end, int* tmp);
void MergeSort(int* a, int n);
void MergeSortNonR(int* a, int n);
void CountSort(int* a, int n);

ST.c

#define _CRT_SECURE_NO_WARNINGS 1#include "ST.h"// 初始化栈
void StackInit(ST* ps)
{assert(ps);ps->a = NULL;ps->capacity = 0;ps->top = 0;
}// 入栈
void StackPush(ST* ps, STDatetype data)
{assert(ps);if (ps->capacity == ps->top){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;ST* newnode = (ST*)realloc(ps->a, newcapacity * sizeof(STDatetype));if (newnode == NULL){perror("recalloc fail");return;}ps->a = newnode;ps->capacity = newcapacity;}ps->a[ps->top] = data;ps->top++;
}// 出栈
void StackPop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));ps->top--;
}// 获取栈顶元素
STDatetype StackTop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top-1];
}// 获取栈中有效元素个数
int StackSize(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->top;
}// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}// 销毁栈
void StackDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0;
}

ST.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>typedef int STDatetype;typedef struct Stack
{STDatetype* a;int top;int capacity;
}ST;// 初始化栈
void StackInit(ST* ps);
// 入栈
void StackPush(ST* ps, STDatetype data);
// 出栈
void StackPop(ST* ps);
// 获取栈顶元素
STDatetype StackTop(ST* ps);
// 获取栈中有效元素个数
int StackSize(ST* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
bool StackEmpty(ST* ps);
// 销毁栈
void StackDestroy(ST* ps);

这个测试结果十分惊人,可以看出冒泡排序和选择排序有多拉跨,值得一提的是计数排序,这个时间是在1ms内所以是0,本来想跑一百万个数但是跑了十分钟没出来,就跑了十万个数了。

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

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

相关文章

[蓝桥杯 2019 省 A] 外卖店优先级

模拟 双指针 #include<iostream> #include<algorithm> using namespace std; using ll long long; #define int long long const int N 1e510; const int inf 0x3f3f3f3f; const int mod 1e97;int n,m,ts;bool vis[N]; int a[N]; int last[N]; pair<int,int…

外卖项目:菜品管理功能代码实现(debug)

文章目录 一、菜品管理功能代码实现1、新增菜品2、菜品分页查询3、修改菜品4、菜品的起售与停售5、删除菜品 一、菜品管理功能代码实现 1、新增菜品 这涉及到多张表&#xff0c;要用事务 添加成功 2、菜品分页查询 3、修改菜品 该页面共涉及4个接口。 接口&#xff1a; 根…

fastutil 代替java 集合框架

背景 java的集合框架中ArrayList&#xff0c;Map&#xff0c;Set等是我们平时最常用的集合类&#xff0c;但是由于这些集合类涉及拆装箱操作&#xff0c;所以内存的消耗比较大&#xff0c;并且性能也不是非常理想&#xff0c;在应付大量的数据时&#xff0c;容易导致gc以及性能…

protobuf原理解析-基于protobuf-c实现序列化,反向序列化

1.一个实例 前面介绍了使用protobuf的流程&#xff0e; (1). 定义proto文件来描述需要序列化和反向序列化传输的消息&#xff0e; (2). 借助proto-c&#xff0c;为proto文件生成对应的代码控制文件&#xff0e; (3). 程序借助生成的代码控制文件和protobuf-c动态库的支持实现类…

如何写出干净的 Git Commit

大家好&#xff0c;我是楷鹏。 写一份干净的 Git Commit&#xff0c;不仅赏心悦目&#xff0c;也有诸多好处&#xff0c;比如 为项目或者仓库生成 change log方便在其他一些 Git 工具使用&#xff0c;比如 CI/CD、代码协作和审计平台、发版工具等 这是 AngularJS 仓库的 Git …

身份证文字识别ocr免费-身份证实名认证接口-护照识别-Java调用代码

文字识别技术是针对图片上的文字进行提取&#xff0c;免去人们手动输入的繁琐。针对证件&#xff0c;翔云提供了身份证识别接口、身份证实名认证接口、护照识别接口&#xff0c;身份证识别接口自动提取身份证信息、身份证实名认证接口实时联网查验身份证的真伪。 以身份证识别…

ActiViz三维场景的基本要素——角色(Actor)

文章目录 前言一、基本属性二、Actor的应用三、高级功能四、示例代码和应用五、总结前言 在ActiViz中,Actor是一种重要的可视化对象,用于表示三维场景中的几何形状、模型或数据。Actors充当了将数据映射到图形管线中的角色,是呈现三维可视化的基础组件之一。通过Actor,用户…

go 解决货币计算的难题:避免浮点数陷阱

在开发的初始阶段&#xff0c;我们经常会遇到“浮点数精度”和“货币值表示”的问题。 那么&#xff0c;如何处理货币&#xff0c;如何存储和传递它们。 为什么是问题&#xff1f; Go语言中的标准浮点类型具有一定的精度&#xff08;像其他任何语言一样&#xff09;&#xf…

前端性能优化:防抖与节流

一、防抖和节流主要是干什么的 防抖和节流主要用于控制函数执行的频率&#xff0c;通过限制函数的触发次数&#xff0c;避免函数被过度调用而引发的性能问题或产生不必要的副作用。 二、防抖 什么是防抖&#xff1a; 防抖的原理是在函数频繁触发时&#xff0c;只执行最后一…

记录(Vue3中常用的组合式API)

Ref 通过组合式API提供的ref函数&#xff0c;可以使数据管理变得更加便利。说得通俗点&#xff0c;就是ref能够使我们在组件内更新这个值 import { ref } from vue; const count ref(0); const increment () > { count.value; }; 以上定义了一个名为count的ref&a…

HiveQL详解

文章目录 前言一、数据定义语言&#xff08;DDL&#xff09;1. 数据库操作1.1 创建数据库1.2 删除数据库1.3 更改数据库1.4 使用数据库 2. 连接器操作2.1 创建连接器2.2 删除连接器2.3 修改连接器 3. 表操作3.1 创建表3.1.1 内部表与外部表3.1.1.1 内部表3.1.1.2 外部表3.1.1.3…

解释关系型数据库和非关系型数据库的区别

一、解释关系型数据库和非关系型数据库的区别 关系型数据库和非关系型数据库在多个方面存在显著的区别。 首先&#xff0c;从数据存储方式来看&#xff0c;关系型数据库采用表格形式&#xff0c;数据存储在数据表的行和列中&#xff0c;且数据表之间可以关联存储&#xff0c;…

短视频矩阵系统技术交付

短视频矩阵系统技术交付&#xff0c;短视频矩阵剪辑矩阵分发系统现在在来开发这个市场单个项目来说&#xff0c;目前基本上已经沉淀3年了&#xff0c;那么我们来就技术短视频矩阵剪辑系统开发来聊聊 短视频矩阵系统经过315大会以后&#xff0c;很多违规的技术开发肯定有筛选到了…

[ C++ ] STL---string类的使用指南

目录 前言&#xff1a; string类简介 string类的常用接口 string类对象的构造函数 string类对象的赋值运算符重载 string类对象的容量操作 string类对象的访问与遍历 [ ] 下标遍历 迭代器遍历 普通迭代器iterator ​编辑 const迭代器const_iterator 反向迭代器rever…

常见的WAFI攻击包括哪些

WIFI攻击是指黑客利用各种手段&#xff0c;对WIFI网络进行非法入侵和攻击&#xff0c;以获取用户的个人信息、网络权限或其他敏感数据。常见的WIFI攻击方式主要包括以下几种&#xff1a;伪造认证页面&#xff1a;黑客可以创建一个伪造的认证页面&#xff0c;当用户尝试连接到WI…

Vue2(三):绑定样式、条件渲染(v-if,v-show)、列表渲染(v-for)、key的原理、列表过滤、列表排序

一、绑定样式 1.绑定class样式 (1)字符串写法 适用于&#xff1a;样式类名不确定&#xff0c;需要动态获取。 <div id"root"><div class"basic" :class"mood" click"changeMood">test</div><!-- class是原本的…

wait()、waitpid()函数的区别(个人总结)

子进程无论是正常或异常退出&#xff0c;内核都会向父进程发送信号 SIGCHILD.&#xff0c;因为无论是使用wait函数&#xff08;阻塞&#xff09;&#xff0c;还是使用waitpid(得循环判断&#xff09;都会将父进程阻塞住&#xff0c;而不能执行别的操作&#xff0c;所以&#xf…

Android Studio实现内容丰富的安卓旅游景点预定

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动 1.开发环境 android stuido3.6 jak1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.查看景点列表 3.查看景点详情 4.景点预定 5.购物车支付结算功能 6…

计算机网络:计算机网络概述

计算机网络&#xff1a;计算机网络概述 因特网概述网络&#xff0c;互连网&#xff0c;因特网因特网发展的三个阶段因特网的标准化工作因特网组成 计算机网络的定义计算机网络的分类按使用者分类按传输介质分类按网络的覆盖范围分类按拓扑结构分类 因特网概述 网络&#xff0c…

红外相机和RGB相机标定:实现两种模态数据融合

1. 前期准备 RGB相机&#xff1a;森云智能SG2-IMX390&#xff0c;1个红外相机&#xff1a;艾睿光电IR-Pilot 640X-32G&#xff0c;1个红外标定板&#xff1a;https://item.taobao.com/item.htm?_ujp3fdd12b99&id644506141871&spma1z09.2.0.0.5f822e8dKrxxYI 2.操作步…