插入排序(一)——直接插入排序与希尔排序

fe594ea5bf754ddbb223a54d8fb1e7bc.gif

目录

一.前言

二.排序的概念及其运用

1.1排序的概念

1.2 常用排序算法

三.常用排序算法的实现

3.1 插入排序

3.1.1 基本思想

3.1.2 直接插入排序

3.1.3 希尔排序(缩小增量排序)

四.全部代码

sort.c

sort.h

test.c

五.结语


8fb442646f144d8daecdd2b61ec78ecd.png一.前言

本文我们开始进入数据结构的难点——排序,当我们初步学习排序后就可以写出更高效的代码~。码字不易,希望大家多多支持我呀!(三连+关注,你是我滴神!)

二.排序的概念及其运用

1.1排序的概念

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

1.2 常用排序算法

三.常用排序算法的实现

3.1 插入排序

3.1.1 基本思想

直接插入排序是一种简单的插入排序法,其基本思想是:

把待排序的记录按其关键码值的大小逐个插入到已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。

实际中我们玩扑克牌时,就用了插入排序的思想

3.1.2 直接插入排序

当插入第i(i>=1)个元素时,前面的arr[0], arr[1]....arr[i-1]已经排行序,此时用arr[i]的排序码与arr[i],arr[i-1],arr[i-2]....的排序码顺序进行比较,找到插入位置即将arr[i]插入,原来位置上的元素顺序后移。

在学习该排序之前我们先完成一个简单的单趟排序。我们对两个有序数组分别插入5和1来分析。

当我们要插入5时,对比最后一位数字,如果该数字比5大则往后挪一位,与此同时end--往前移动继续与5比较,以此类推直到end指向4(比5小)的时候停下,然后在end的后面插入5.

接下来对于1也是同理,当对比完发现end指向-1时1成功插入(1为最小)。

基于这两个图例我们来开始写这个单趟代码:

首先要在有序数组插入数字的时候,那么5的位置肯定是end+1位,其次我们需要用tmp来保存5因为当9往后挪动的时候会覆盖5的位置,要想让5继续与前面数字进行比较就得用存储5的tmp。

void InsertSort(int* arr, int n)
{//单趟排序int end = n - 2;int tmp = arr[end + 1];while (end >= 0){if (tmp < arr[end])//如果遇到比tmp大的数{arr[end + 1] = arr[end];//往后挪}else{break;//退出循环,在外面插入}end--;}arr[end + 1] = tmp;
}int main()
{int arr[] = { 3,4,2,1,7,8,5 };InsertSort(arr, 7);return 0;
}

有一点需要注意,当我们在可以插入的时候不能选择在循环里面插入而是用break跳出循环,再写插入的代码。

之所以这样是因为如果tmp保存的值比数组中所有的值都要小,那么它只能是等到循环结束,是不能在循环里进行插入的。

 

既然我们控制了单趟有序,怎么样控制整体有序呢? 

我们只需要控制end的位置就可以做到整体有序,因为这就像是一个在有序数组里不断插入的过程,而end的起始位置作用就是隔离有序数组。

所以end的范围起始是0结束应该是n-2。在n个数中,end指向倒数第2个,把倒数第一个当作要插入的数字即可完成所有的排序。

void InsertSort(int* arr, int n)
{int i = 0;for (i = 0; i < n - 1; i++){//单趟排序int end = i;int tmp = arr[end + 1];while (end >= 0){if (tmp < arr[end])//如果遇到比tmp大的数{arr[end + 1] = arr[end];//往后挪}else{break;//退出循环,在外面插入}end--;}arr[end + 1] = tmp;}}int main()
{int arr[] = { 3,4,2,1,7,8,5 };InsertSort(arr, 7);return 0;
}

时间复杂度:

最坏情况(逆序时):O(N^2)

最好情况(顺序有序时):O(N) 

直接插入排序的特性总结:

  1. 元素集合越接近有序,直接插入排序算法的时间效率越高
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1),它是一种稳定的排序算法
  4. 稳定性:稳定

3.1.3 希尔排序(缩小增量排序)

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成各组,所有距离为gap的记录分在同一组内,并对每一组内的记录进行排序,然后去重复上述分组和排序的工作。当到达gap=1时,所有的记录在统一组内排好序。

希尔排序前景:

  1. 先预排序
  2. 直接插入排序

我们通过预排序让数组接近有序再来直接插入排序这样时间复杂度就可以接近O(N)

接着我们要在划分好的组里进行直接插入排序

蓝色组:

紫色组:

红色组:

在外面排完之后可以观察得到,现在这组数虽然不是有序,但对比原有顺序可以说是相对有序(大的数更往后排了,小的数更往前排了)。

接下来我们用代码来实现该思路:

在直接插入的基础上进行修改

以此类推完成排序

void ShellSort(int* a, int n)
{//单趟排序int gap = 3;int end = 0;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end])//如果遇到比tmp大的数{a[end + gap] = a[end];//往后挪}else{break;//退出循环,在外面插入}end = end - gap;}a[end + gap] = tmp;}

我们可以发现如果gap为1时,那就是直接插入排序了~

这样就控制了蓝色一组

void ShellSort(int* a, int n)
{int gap = 3;for (int i = 0; i < n ; i += gap){//单趟排序int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end])//如果遇到比tmp大的数{a[end + gap] = a[end];//往后挪}else{break;//退出循环,在外面插入}end = end - gap;}a[end + gap] = tmp;}}

那么按照这个代码,最后end一定要落到这个位置上吗? 

如果落到这个位置,那最后tmp再取end+1就越界了,而且按照我们上面学到的插排,end起始排序的位置是要落在插入数字之前的,但目前end的位置在蓝色组中是最后一个数字,使得其tmp取到随机值了。

所以最后我们要选的是n-gap,因为这里条件是i小于,所以最后end的位置才可以落在n-4即8所在的位置,而这在蓝色组的4个数字中排序是最后落到为倒数第二个数字,符合直接插入的规则。

void ShellSort(int* a, int n)
{int gap = 3;for (int i = 0; i <n-gap; i+=gap){//单趟排序int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end])//如果遇到比tmp大的数{a[end + gap] = a[end];//往后挪}else{break;//退出循环,在外面插入}end = end-gap;}a[end + gap] = tmp;}
}

现在我们把蓝色组的预排序处理好了,那另外两组又要如何处理?

再来套个循环去改变它们的起始位置就行了。

void ShellSort(int* a, int n)
{int gap = 3;for (int j = 0; j < gap; j++){for (int i = j; i < n - gap; i += gap){//单趟排序int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end])//如果遇到比tmp大的数{a[end + gap] = a[end];//往后挪}else{break;//退出循环,在外面插入}end = end - gap;}a[end + gap] = tmp;}}}

这样子是一组一组排,蓝色走完走紫色,紫色走完走红色。

下面是另一种版本(效果与上面一样):多组并排

void ShellSort(int* a, int n)
{int gap = 3;for (int i = 0; i < n - gap; ++i){//单趟排序int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end])//如果遇到比tmp大的数{a[end + gap] = a[end];//往后挪}else{break;//退出循环,在外面插入}end = end - gap;}a[end + gap] = tmp;}}

 

这个是挨个排序(蓝紫红蓝紫红,虽然效果跟前面的一样,但前面代码明显更好理解~

预排序意义:大的数更快的到后面去,小的数更快的到前面去。gap越大跳的越快,越不接近有序,gap越小跳的越慢,越接近有序。gap=1,直接有序。 

完整希尔排序 

void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap = gap / 2;for (int j = 0; j < gap; j++){for (int i = j; i < n - gap; i += gap){//单趟排序int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end])//如果遇到比tmp大的数{a[end + gap] = a[end];//往后挪}else{break;//退出循环,在外面插入}end = end - gap;}a[end + gap] = tmp;}}}}

之所以这样是因为gap不好给固定的值,固定值有时候会不适合n的数量变化,所以我们最开始可以先让gap为n,然后通过/2的方式对数组不断进行预排序,而在最后gap一定是为1,这时候就可以进行整体的排序了。 

有时候为避免预排序过多可以改变一下gap,/3+1是为了保证gap最后能够取到1

接下来我们来测试一下它的性能

这是通过生成100000个随机值测试用的代码片段。

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);for (int i = N-1; i >= 0; --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];}int begin1 = clock();InsertSort(a1, N);int end1 = clock();int begin2 = clock();ShellSort(a2, N);int end2 = clock();int begin7 = clock();//BubbleSort(a7, N);int end7 = clock();int begin3 = clock();//SelectSort(a3, N);int end3 = clock();int begin4 = clock();//HeapSort(a4, N);int end4 = clock();int begin5 = clock();//QuickSort(a5, 0, N - 1);int end5 = clock();int begin6 = clock();//MergeSort(a6, N);int end6 = clock();printf("InsertSort:%d\n", end1 - begin1);printf("ShellSort:%d\n", end2 - begin2);printf("BubbleSort:%d\n", end7 - begin7);printf("SelectSort:%d\n", end3 - begin3);printf("HeapSort:%d\n", end4 - begin4);printf("QuickSort:%d\n", end5 - begin5);printf("MergeSort:%d\n", end6 - begin6);free(a1);free(a2);free(a3);free(a4);free(a5);free(a6);free(a7);
}int main()
{TestOP();//TestBubbleSort();//TestHeapSort();//TestSelectSort();return 0;
}

我们选择调用希尔和插排来对比在10万个随机数中二者排序完成的用时是多少。

我们再来看看1万个数据的效果

可以发现数据量越大越能突显希尔的性能优势。

希尔排序的时间复杂度

一般gap是多少就会划分有多少个组别

gap很大的时候,如n/3 整个数组逆序,n/3组数据,每组比较3次(1+2)间距为gap的这些数据,合计 n/3 *3 ==n

所以我们可以得知红框框住的这两组循环一开始是n次

gap很大的时候,如1 接近有序了 间距为1的这些数据,合计:n

中间会呈现由n变大再变小到n的过程。

我们粗略通过循环比较可以得出时间复杂度N(因为上图中n无法精确计算)*logN(以2为底或以3为底,看gap怎么处理)。

而最终结论是,时间复杂度为O(N^1.3),算法效率略差于n*logn

四.全部代码

sort.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "sort.h"
void InsertSort(int* arr, int n)
{int i = 0;for (i = 0; i < n - 1; i++){//单趟排序int end = i;int tmp = arr[end + 1];while (end >= 0){if (tmp < arr[end])//如果遇到比tmp大的数{arr[end + 1] = arr[end];//往后挪}else{break;//退出循环,在外面插入}end--;}arr[end + 1] = tmp;}}//void ShellSort(int* a, int n)
//{
//	int gap = 3;
//	for (int i = 0; i < n ; i += gap)
//	{
//		//单趟排序
//		int end = i;
//		int tmp = a[end + gap];
//		while (end >= 0)
//		{
//			if (tmp < a[end])//如果遇到比tmp大的数
//			{
//				a[end + gap] = a[end];//往后挪
//			}
//			else
//			{
//				break;//退出循环,在外面插入
//			}
//			end = end - gap;
//		}
//		a[end + gap] = tmp;
//	}
//
//
//}void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap = gap / 2;for (int j = 0; j < gap; j++){for (int i = j; i < n - gap; i += gap){//单趟排序int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end])//如果遇到比tmp大的数{a[end + gap] = a[end];//往后挪}else{break;//退出循环,在外面插入}end = end - gap;}a[end + gap] = tmp;}}}}
//void ShellSort(int* a, int n)
//{
//	int gap = 3;
//	for (int i = 0; i < n - gap; ++i)
//	{
//		//单趟排序
//		int end = i;
//		int tmp = a[end + gap];
//		while (end >= 0)
//		{
//			if (tmp < a[end])//如果遇到比tmp大的数
//			{
//				a[end + gap] = a[end];//往后挪
//			}
//			else
//			{
//				break;//退出循环,在外面插入
//			}
//			end = end - gap;
//		}
//		a[end + gap] = tmp;
//	}
//
//}void PrintfSort(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");
}

—————————————————————————————————————————— 

sort.h

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>void PrintfSort(int* a, int n);void ShellSort(int* a, int n);void InsertSort(int* arr, int n);

—————————————————————————————————————————— 

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "sort.h"
#include <time.h>
#include <stdlib.h>
//void InsertSort(int* arr, int n)
//{
//	int i = 0;
//	for (i = 0; i < n - 1; i++)
//	{
//		//单趟排序
//		int end = i;
//		int tmp = arr[end + 1];
//		while (end >= 0)
//		{
//			if (tmp < arr[end])//如果遇到比tmp大的数
//			{
//				arr[end + 1] = arr[end];//往后挪
//			}
//			else
//			{
//				break;//退出循环,在外面插入
//			}
//			end--;
//		}
//		arr[end + 1] = tmp;
//	}
//	
//}
void TestShellSort()
{int a[] = { 9,1,2,5,7,4,8,6,3,5,1,2,3,5,1,8,3 };ShellSort(a, sizeof(a) / sizeof(int));PrintfSort(a, sizeof(a) / sizeof(int));
}void TestOP()
{srand(time(0));const int N = 10000;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);for (int i = N - 1; i >= 0; --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];}int begin1 = clock();InsertSort(a1, N);int end1 = clock();int begin2 = clock();ShellSort(a2, N);int end2 = clock();int begin7 = clock();//BubbleSort(a7, N);int end7 = clock();int begin3 = clock();//SelectSort(a3, N);int end3 = clock();int begin4 = clock();//HeapSort(a4, N);int end4 = clock();int begin5 = clock();//QuickSort(a5, 0, N - 1);int end5 = clock();int begin6 = clock();//MergeSort(a6, N);int end6 = clock();printf("InsertSort:%d\n", end1 - begin1);printf("ShellSort:%d\n", end2 - begin2);printf("BubbleSort:%d\n", end7 - begin7);printf("SelectSort:%d\n", end3 - begin3);printf("HeapSort:%d\n", end4 - begin4);printf("QuickSort:%d\n", end5 - begin5);printf("MergeSort:%d\n", end6 - begin6);free(a1);free(a2);free(a3);free(a4);free(a5);free(a6);free(a7);
}int main()
{//int arr[] = { 3,4,2,1,7,8,5 };//InsertSort(arr, 7);/*int a[] = {1,5,8,7,4,6,9,85,2,4,1,7 };ShellSort(a, sizeof(a) / sizeof(int));PrintfSort(a, sizeof(a) / sizeof(int));*/TestOP();return 0;
}

 

4b12323f94834afd9ec146a3c10df229.jpeg五.结语

插入排序只是排序中的冰山一角,它可以帮助我们处理更庞大的数据,不过由于排序算法有多种,我们得学会在各种情况下运用最佳算法进行排序。最后感谢大家的观看,友友们能够学习到新的知识是额滴荣幸,期待我们下次相见~

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

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

相关文章

航空飞行器运维VR模拟互动教学更直观有趣

传统的二手车鉴定评估培训模式存在实践性不强、教学样本不足、与实际脱节等一些固有的不足。有了VR虚拟仿真技术的加持&#xff0c;二手车鉴定评估VR虚拟仿真实训系统逐渐进入实训领域&#xff0c;为院校及企业二手车检测培训提供了全新的解决方案。 高职院校汽车专业虚拟仿真实…

DC-3靶机刷题记录

靶机下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1-P5ezyt5hUbmmGMP4EI7kw?pwdrt2c 提取码&#xff1a;rt2c 参考&#xff1a; http://t.csdnimg.cn/hhPi8https://www.vulnhub.com/entry/dc-32,312/ 官网http://t.csdnimg.cn/5mVZ7DC-3 (1).pdfhttps://…

模具制造企业ERP系统有哪些?企业怎么选型适配的软件

模具的生产管理过程比较繁琐&#xff0c;涵盖接单报价、车间排期、班组负荷评估、库存盘点、材料采购、供应商选择、工艺流转、品质检验等诸多环节。 有些采用传统管理手段的模具制造企业存在各业务数据传递不畅、信息滞后、不能及时掌握订单和车间生产情况&#xff0c;难以对…

【CF比赛记录】 —— Codeforces Round 920 (Div. 3)(A、B、C、D)

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;CF比赛记录 &#x1f48c;其他专栏&#xff1a; &#x1f534;每日一题 &#x1f7e1; cf闯关练习 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓…

【ARMv8M Cortex-M33 系列 7.1 -- xPSR | CFSR | HFSR | BFAR | MMFAR 寄存器】

文章目录 问题背景Cortex-M33 Fault 寄存器介绍xPSR (程序状态寄存器)CFSR (可配置故障状态寄存器)HFSR (硬件故障状态寄存器)BFAR (总线故障地址寄存器)MMFAR (内存管理故障地址寄存器) 问题背景 由于在RA4M2&#xff08;Cortex-M33&#xff09;移植RT-Thread OS的时候遇到了…

第十五届蓝桥杯单片机组——串口通信UART

文章目录 一、什么是串口通信二、UART重要参数三、利用STC-ISP生成初始化代码四、使用UART发送和接收数据 一、什么是串口通信 微控制器与外部设备的数据通信&#xff0c;根据连线结构和传送方式的不同&#xff0c;可以分为两种:并行通信和串行通信。   并行通信:指数据的各位…

亚马逊云科技 WAF 部署小指南(六)追踪 Amazon WAF Request ID,排查误杀原因

众所周知&#xff0c;中国是全球制造业的巨大力量&#xff0c;许多中国企业通过 2B 电商平台网站进行商品销售和采购。在这些电商平台上&#xff0c;Web 应用防火墙&#xff08;WAF&#xff09;成为不可或缺的安全工具。然而&#xff0c;WAF 也可能导致误杀问题。一旦误杀发生&…

计算机毕设thinkphp+mysql+_vue房屋租赁系统h3sem

运行环境:phpstudy/wamp/xammp等 开发语言&#xff1a;php 后端框架&#xff1a;Thinkphp5 前端框架&#xff1a;vue.js 服务器&#xff1a;apache 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat/phpmyadmin 房屋租赁管理系统有不同的用户角色。不同的用户权限对应不…

【办公类-21-03】20240119 提取不连续的男女学号 set()和list法

背景需求&#xff1a;了解班级幼儿性别比例 查看点名册&#xff0c;发现中4班最初的学号是按照先男后女的方式排列&#xff0c;但是随着幼儿转出&#xff0c;空出一些学号&#xff0c;于是新插班的孩子就插入空的学号&#xff0c;空格插完了&#xff0c;就排在学号尾部。 我想…

Docker Consul详解与部署示例

目录 Consul构成 Docker Consul 概述 Raft算法 服务注册与发现 健康检查 Key/Value存储 多数据中心 部署模式 consul-template守护进程 registrator容器 consul服务部署&#xff08;192.168.41.31&#xff09; 环境准备 搭建Consul服务 查看集群信息 registrato…

YOLOv5改进 | 主干篇 | 华为GhostnetV1一种移动端的专用特征提取网络

一、本文介绍 本文给大家带来的改进机制是华为移动端模型Ghostnetv1,华为GhostnetV1一种移动端的专用特征提取网络,旨在在计算资源有限的嵌入式设备上实现高性能的图像分类。GhostNet的关键思想在于通过引入Ghost模块,以较低的计算成本增加了特征图的数量,从而提高了模型的…

深度剖析Spring循环依赖(实战Bug)

目录 前言1. 问题所示2. 原理分析3. 基本知识4. Lazy注解 前言 通过实战更好的回馈问题&#xff0c;意识更加深刻 起因是我出现如下问题之后&#xff0c;才意识到中了Spring的循环依赖了&#xff01; 1. 问题所示 在执行项目的时候&#xff0c;出现如下问题&#xff0c;问题…

面试之Glide如何绑定Activity的生命周期

Glide绑定Activity生命周期 Glide.with() 下面都是它的重载方法&#xff0c;Context&#xff0c;Activity&#xff0c;FragmentActivity, Fragment, android.app.Fragment fragment,View都可以作为他的参数&#xff0c;内容大同小异&#xff0c;都是先getRetriever&#xff0…

016-Vue-黑马2023:前后端分离开发(在线接口文档),前端工程化、Element、vue编写一个完成页面、Vue路由、vue打包部署到nginx

第三节 前后端分离开发 1、介绍 开发模式 前后端混合开发&#xff1a;传统开发模式 前后端分离开发&#xff1a;当前最为主流的开发模式 页面原型需求案例&#xff1a;分析出接口文档 离线开发文档示例&#xff1a; 2、YAPI&#xff08;官网已停用&#xff09; 202…

汽车微电机行业研究:预计2029年将达到188亿美元

微电机行业是技术密集型行业&#xff0c;其起源于欧洲的德国、瑞士等国家&#xff0c;发展于日本。随着改革开放&#xff0c;中国作为发展中国家&#xff0c;承接了德国、日本等发达国家的汽车微电机产业转移&#xff0c;技术扩散逐步向我国转移。 微特电机广泛应用于信息处理设…

优化微信小程序更新体验:异步更新与强制更新方案解析

在微信小程序的开发和迭代过程中&#xff0c;新版本覆盖率的问题一直备受关注。由于小程序采用异步更新机制&#xff0c;在用户首次打开或冷启动时才会检查并下载新版本&#xff0c;导致部分用户无法及时应用上最新版本。为了解决这一问题&#xff0c;微信团队经过深入研究和讨…

设计社交网络的数据结构

1: 确定 Use Case 和 约束 Use Cases User 搜索某人然后看到被搜索人的最短路径Service 有高可用 约束和假设 状态假设 Traffic 不是平均分布的 一些被搜索者是更加受欢迎的&#xff0c;某些被搜索者只会被搜索一次图数据不适用与单个机器图的分布是轻量级的一亿个 User每…

canvas绘制N角形,锯齿状

查看专栏目录 canvas实例应用100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

在线扒站网PHP源码-在线扒站工具网站源码

源码介绍 这是一款在线的网站模板下载程序&#xff0c;也就是我们常说的扒站工具&#xff0c;利用它我们可以很轻松的将别人的网站模板样式下载下来&#xff0c;这样就可以大大提高我们编写前端的速度了&#xff01;注&#xff1a;扒取的任何站点不得用于商业、违法用途&#…

kafka参数配置参考和优化建议 —— 筑梦之路

对于Kafka的优化&#xff0c;可以从以下几个方面进行思考和优化&#xff1a; 硬件优化&#xff1a;使用高性能的硬件设备&#xff0c;包括高速磁盘、大内存和高性能网络设备&#xff0c;以提高Kafka集群的整体性能。 配置优化&#xff1a;调整Kafka的配置参数&#xff0c;包括…