数据结构:七种排序及总结
文章目录
- 排序
- 一插入排序
- 1直接插入排序
- 2希尔排序
- 二选择排序
- 3直接选择排序
- 4堆排序
- 三 交换排序
- 5冒泡排序
- 6快速排序
- 四 归并排序
- 7归并排序
- 源码
排序
我们数据结构常见的排序有四大种,四大种又分为七小种,如图所示
排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次
序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排
序算法是稳定的;否则称为不稳定的。
内部排序:数据元素全部放在内存中的排序。
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不断地在内外存之间移动数据的排序。
一插入排序
1直接插入排序
void InsertSort(int* a, int n);
从i=0开始遍历,每次i之前的序列都是有序的,通过判断当前i的值能够在i之前哪个位置,找到后直接插入,
为什么直接插入排序最坏的情况是n^2?
如果一个开始原序列是降序,想排为升序
第一个循环是n,第二个循环最坏是n,所以是最大n^2
void InsertSort(int* arr, int n) {for (int i = 0; i < n-1; i++) {int end = i;int tem = arr[end + 1];while (end >= 0) {if (arr[end] > tem) {arr[end + 1] = arr[end];end--;}else{break;}}arr[end + 1] = tem;}}
2希尔排序
希尔排序是对直接插入排序的优化,大大优化了时间复杂度
他们是先规定了一个gap值,然后每次进行循环把gap值缩小,最后把 gap值调为1。这样最后一次排序就是直接插入排序,前面的是预排序。
条件就是
while(gap>1){
gap=gap/3+1;//最后一次gap=1随后跳出循环}
void ShellSort(int* arr, int n) {int gap = n;while(gap>1){gap = gap / 3 + 1;for (int i = 0; i < n - gap; i++) {int end = i;int tem = arr[end +gap];while (end >= 0) {if (arr[end] > tem) {arr[end + gap] = arr[end];end-=gap;}else{break;}}arr[end + gap] = tem;} }}
判断两种排序的时间复杂度
二选择排序
3直接选择排序
直接选择排序就是一种很暴力的解法,思路简单,代码简单,但是时间复杂度很差,和 冒泡排序差不多
思路就是分别从两头找最大和最小,然后对下标进行++ – 然后直到相遇。
void SeletSort(int* arr, int n) {int end = n - 1;int begin = 0;int max, min;max = min = 0;while (begin < end) {max = min = begin;for (int i = begin + 1; i <= end; i++){if (arr[i] > arr[max]) {max = i;}if (arr[i] < arr[min]){min = i;}}if (max == begin) {max = min;}Swap(&arr[min], &arr[begin]);Swap(&arr[max], &arr[end]);begin++;end--;}}
有一种特殊情况要处理就是换的时候max在begin位置,因为先&arr[min], &arr[begin]换,所以要提前max=min.(此时最大值在min下标位置)
if (max == begin) { max = min; }
时间复杂度n*(n/2+n/2)=n^2.
4堆排序
要了解堆排序我们要先了解一些误区:
1无论向下调整算案建堆还是向上调整算法建堆都是形成一个二叉树结构,本身并没有让数组完全有序,
2向下调整算法建堆比向上调整算法建堆时间复杂度更优
3排升序建大堆,排降序 建小堆。
所以我们要先完成堆排序的话要完成两个步骤,
1把原序列进行向下或向上调整遍历,成为一个堆的结构,
2因为头结点一定是最值,我们每次把arr[0]和arr[end]交换,再让end–完成之后就完成排序。
void HeapSort(HeapType* arr, int n) {//第一步for (int i = (n - 1 - 1) / 2; i >= 0; i--) {AdjustDown(arr, i, n);}int end = n - 1;for (int i = end; i > 0; i--) {//第二步Swap(&arr[0], &arr[end]);AdjustDown(arr, 0, end);end--;}
}
因为向下调整算法建堆的时间复杂度大概是O(n)
第二部大概是O(nlogn)
故时间复杂度O(n+nlogn)大概是O(n*logn).
三 交换排序
5冒泡排序
冒泡排序两层循环o(n^2)
加上优化还是最好情况O(n)所以是O(n^2)
void BubbleSort(int* a, int n) {for (int i = 0; i < n - 1; i++){int xz = 0;for (int j = 0; j < n - i - 1; j++) {if (a[j] > a[j + 1]) {swap(&a[j], &a[j + 1]);xz = 1;}}if (xz == 0) {break;}}}
6快速排序
快排我们用的找中间值 ,然后分区间,类似堆排序,时间复杂度o(nlogn)
按最情况来说,每次循环排最差情况是n/2+n/2=n,一共是logn次循环(最好情况,每次中间值恰好在中间)
按最坏情况是n次循环,所以时间复杂度为nlogn~n^2.
int GetKeyi(int* arr, int left, int right) {int keyi = left;left++;while (right>=left){while (left<=right&&arr[right]>arr[keyi]) {right--;}while (left <= right && arr[left] < arr[keyi]) {left++;}if (left <= right) {swap(&arr[right--], &arr[left++]);}}swap(&arr[keyi], &arr[right]);return right;
}
void QuickSort(int* arr, int left,int right) {if (left >= right) {return;}int keyi = GetKeyi(arr, left, right);QuickSort(arr, left,keyi - 1);QuickSort(arr, keyi+1,right);}
四 归并排序
7归并排序
归并排序的思想是通过二分找中间值,[left,中间值] ,[中间值+1,right]两个序列再二分,直到left>=中间值,然后通过递归返回原来的函数栈帧进行排序,因为只有logn个函数栈帧,每次栈帧内最坏排n个数据。
为了不破坏arr序列,我们定义了tem序列接收,然后最后把tem数组覆盖arr,
时间复杂度为n*logn
void MergeSort(int* arr, int n) {int* tem = (int*)malloc(sizeof(int) * n);_MergeSort(arr,0, n - 1,tem);free(tem);}
void _MergeSort(int* arr, int left, int right, int* tem) {if (left >= right) {return;}int mid = (left + right) / 2;_MergeSort(arr, left, mid, tem);_MergeSort(arr, mid+1, right, tem);int begin1 = left;int begin2 = mid + 1;int end1 = mid;int end2 = right;int x = begin1;while (begin1 <= end1 && begin2 <= end2) {if (arr[begin1] < arr[begin2]) { tem[x++] = arr[begin1++];}else{tem[x++] = arr[begin2++];}}while (begin1 <= end1) {tem[x++] = arr[begin1++];}while (begin2 <= end2) {tem[x++] = arr[begin2++];}for (int i = left; i < right; i++){arr[i] = tem[i];}
}
最后总结一下所有排序时间
源码
Sort.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<assert.h>
#include<stdbool.h>
typedef int HeapType;
typedef struct Heap {HeapType* a;int capacity;int size;}Heap;
void SeletSort(HeapType* arr, int n);
void Inite(Heap* p);
void Push(Heap* p, HeapType x);
void Pop(Heap* p);
bool Empty(Heap* p);
HeapType Top(Heap* p);
void Print(Heap* p);
void Destry(Heap* p);
void Swap(HeapType* a, HeapType* b);
void AdjustUp(HeapType* a, int child);
void AdjustDown(HeapType* a, int parent, int n);
void HeapSort(HeapType* arr, int n);void BubbleSort(int* a, int n);
void swap(int* a, int* b);
void InsertSort(int* arr, int n);
void ShellSort(int* arr, int n);
int GetKeyi(int* arr, int left, int right);
void QuickSort(int* arr, int left, int right);
void MergeSort(int* arr,int n);
void _MergeSort(int* arr, int left, int right, int* tem);void test();
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Sort.h"
#include"time.h"
#include"stdlib.h"int main() {test();return 0;
}
Sort.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Sort.h"void test() {srand((unsigned)time(0));const int N = 100000;int* a1 = (int*)malloc(sizeof(int) * N);//创建100000个空间的数组int* a2 = (int*)malloc(sizeof(int) * N);//创建100000个空间的数组int* a3 = (int*)malloc(sizeof(int) * N);//创建100000个空间的数组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 = 0; i < N; i++) {a1[i] = rand();//循环100000次,每次赋予a1数组随机值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 begin3= clock();SeletSort(a3, N);int end3 = clock();int begin4 = clock();HeapSort(a4, N);int end4 = clock();int begin5 = clock();BubbleSort(a5, N);int end5 = clock();int begin6= clock();QuickSort(a6, 0,N-1);int end6 = clock();int begin7 = clock();MergeSort(a7, N - 1);int end7 = clock();printf("InsertSort:%d\n", end1 - begin1);printf("ShellSort:%d\n", end2 - begin2);printf("SelectSort:%d\n", end3 - begin3);printf("HeapSort:%d\n", end4 - begin4);printf("BubbleSort:%d\n", end5 - begin5);printf("QuickSort:%d\n", end6 - begin6);printf("MergeSort:%d\n", end7 - begin7);}
void swap(int* a, int* b) {int tmp = *a;*a = *b;*b = tmp;}
void BubbleSort(int* a, int n) {for (int i = 0; i < n - 1; i++){int xz = 0;for (int j = 0; j < n - i - 1; j++) {if (a[j] > a[j + 1]) {swap(&a[j], &a[j + 1]);xz = 1;}}if (xz == 0) {break;}}}void InsertSort(int* arr, int n) {for (int i = 0; i < n - 1; i++) {int end = i;int tem = arr[end + 1];while (end >= 0) {if (arr[end] > tem) {arr[end + 1] = arr[end];end--;}else{break;}}arr[end + 1] = tem;}}
void ShellSort(int* arr, int n) {int gap = n;while (gap > 1) {gap = gap / 3 + 1;for (int i = 0; i < n - gap; i++) {int end = i;int tem = arr[end + gap];while (end >= 0) {if (arr[end] > tem) {arr[end + gap] = arr[end];end -= gap;}else{break;}}arr[end + gap] = tem;}}}
void SeletSort(int* arr, int n) {int end = n - 1;int begin = 0;int max, min;max = min = 0;while (begin < end) {max = min = begin;for (int i = begin + 1; i <= end; i++){if (arr[i] > arr[max]) {max = i;}if (arr[i] < arr[min]){min = i;}}if (max == begin) {max = min;}Swap(&arr[min], &arr[begin]);Swap(&arr[max], &arr[end]);begin++;end--;}}
void Inite(Heap* p) {p->a = NULL;p->capacity = p->size = 0;}
void Push(Heap* php, HeapType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HeapType* tmp = (HeapType*)realloc(php->a, newcapacity * sizeof(HeapType));if (tmp == NULL){perror("realloc fail");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}
void Pop(Heap* p) {Swap(&p->a[0], &p->a[p->size - 1]);p->size--;AdjustDown(p->a, 0, p->size);}
bool Empty(Heap* p) {return p->size == 0;}
HeapType Top(Heap* p) {return p->a[0];}
void Print(Heap* p) {{while (!Empty(p)){printf("%d ", Top(p));Pop(p);}}
}
void Swap(HeapType* a, HeapType* b) {int tem = *a;*a = *b;*b = tem;}
void AdjustUp(HeapType* a, int child) {int parent = (child - 1) / 2;while (child > 0) {if (a[child] < a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void AdjustDown(HeapType* a, int parent, int n) {int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child] > a[child + 1]) {child = child + 1;}if (a[parent] > a[child]) {Swap(&a[parent], &a[child]);parent = child;child = child * 2 + 1;}else{break;}}}
void HeapSort(HeapType* arr, int n) {for (int i = (n - 1 - 1) / 2; i >= 0; i--) {AdjustDown(arr, i, n);}int end = n - 1;for (int i = end; i > 0; i--) {Swap(&arr[0], &arr[end]);AdjustDown(arr, 0, end);end--;}
}
int GetKeyi(int* arr, int left, int right) {int keyi = left;left++;while (right>=left){while (left<=right&&arr[right]>arr[keyi]) {right--;}while (left <= right && arr[left] < arr[keyi]) {left++;}if (left <= right) {swap(&arr[right--], &arr[left++]);}}swap(&arr[keyi], &arr[right]);return right;
}
void QuickSort(int* arr, int left,int right) {if (left >= right) {return;}int keyi = GetKeyi(arr, left, right);QuickSort(arr, left,keyi - 1);QuickSort(arr, keyi+1,right);}
void MergeSort(int* arr, int n) {int* tem = (int*)malloc(sizeof(int) * n);_MergeSort(arr,0, n - 1,tem);free(tem);}
void _MergeSort(int* arr, int left, int right, int* tem) {if (left >= right) {return;}int mid = (left + right) / 2;_MergeSort(arr, left, mid, tem);_MergeSort(arr, mid+1, right, tem);int begin1 = left;int begin2 = mid + 1;int end1 = mid;int end2 = right;int x = begin1;while (begin1 <= end1 && begin2 <= end2) {if (arr[begin1] < arr[begin2]) { tem[x++] = arr[begin1++];}else{tem[x++] = arr[begin2++];}}while (begin1 <= end1) {tem[x++] = arr[begin1++];}while (begin2 <= end2) {tem[x++] = arr[begin2++];}for (int i = left; i < right; i++){arr[i] = tem[i];}
}
相关文章:

数据结构:七种排序及总结
文章目录 排序一插入排序1直接插入排序2希尔排序二选择排序3直接选择排序4堆排序三 交换排序5冒泡排序6快速排序四 归并排序7归并排序源码 排序 我们数据结构常见的排序有四大种,四大种又分为七小种,如图所示 排序:所谓排序,就是…...

【安当产品应用案例100集】030-使用企业微信登录Windows,实现工作电脑与业务系统登录方式统一
随着越来越多的企业信息系统从intranet开放到internet,企业员工的办公接入方式也越发多样,信息系统面临的数据安全问题也呈现爆发的趋势。一些大企业,比如Google、Microsoft、Huawei有强大的开发能力、IT能力,可以构建出自己的零信…...
大数据数据存储层MemSQL, HBase与HDFS
以下是对 MemSQL、HBase 和 HDFS 的详细介绍,这些工具在分布式数据存储和处理领域有着重要作用。 1. MemSQL MemSQL(现称为 SingleStore)是一种分布式内存数据库,兼具事务处理(OLTP)和分析处理(OLAP)的能力,专为高性能实时数据处理设计。 1.1 核心特点 内存优先存储…...

【HarmonyOS】鸿蒙应用设置控件通用样式AttributeModifier, @Styles
【HarmonyOS】鸿蒙应用设置控件通用样式AttributeModifier, Styles 前言 在鸿蒙中UI开发经常需要对控件样式进行统一的封装,在API早前版本,一般是通过 Styles进行样式封装复用: Entry Component struct Index {build() {Column(…...
Scala IF...ELSE 语句
Scala IF...ELSE 语句 Scala 是一种多范式的编程语言,它结合了面向对象和函数式编程的特点。在 Scala 中,if...else 语句是一种基本且常用的控制结构,用于根据条件执行不同的代码块。与 Java 或 Python 等其他语言中的 if...else 语句类似&a…...

快速上手vue3+js+Node.js
安装Navicat Premium Navicat Premium 创建一个空的文件夹(用于配置node) 生成pakeage.json文件 npm init -y 操作mysql npm i mysql2.18.1 安装express搭建web服务器 npm i express4.17.1安装cors解决跨域问题 npm i cors2.8.5创建app.js con…...

06 网络编程基础
目录 1.通信三要素 1. IP地址(Internet Protocol Address) 2. 端口号(Port Number) 3. 协议(Protocol) 2.TCP与UDP协议 三次握手(Three-Way Handshake) 四次挥手(…...
Python 的 FastApi 如何在request 重复取request.body()
需求背景: 需要再中间件中获取body 中的信息 但是 又想要在之后 还可以重复取 这个body 因为有的接口写法是直接从body中获取参数,然而这个body是数据流的形式,一旦取一次就导致后面取不到里面的值了 。 解决方式: 1.保存请求体: 在中间件中读取请求…...

qt QFontDialog详解
1、概述 QFontDialog 是 Qt 框架中的一个对话框类,用于选择字体。它提供了一个可视化的界面,允许用户选择所需的字体以及相关的属性,如字体样式、大小、粗细等。用户可以通过对话框中的选项进行选择,并实时预览所选字体的效果。Q…...

AI时代,通才可能会占据更有利的地位
在AI时代,通才不仅有生存的可能,而且根据多个参考内容,他们实际上可能占据更有利的地位。以下几点解释了为什么通才在人工智能时代具有重要性和生存空间: 适应性和灵活性:通才因其广泛的知识基础和跨领域的技能&#x…...

qt QHeaderView详解
1、概述 QHeaderView 是 Qt 框架中的一个类,它通常作为 QTableView、QTreeView 等视图类的一部分,用于显示和管理列的标题(对于水平头)或行的标题(对于垂直头)。QHeaderView 提供了对这些标题的排序、筛选…...

探索PickleDB:Python中的轻量级数据存储利器
文章目录 探索PickleDB:Python中的轻量级数据存储利器1. 背景:为什么选择PickleDB?2. PickleDB是什么?3. 如何安装PickleDB?4. 简单的库函数使用方法创建和打开数据库设置数据获取数据删除数据保存数据库 5. 应用场景与…...
yocto下编译perf失败的解决方法
文章目录 问题分析库没有安装?文件缺少?解决参考问题 在新环境使用yocto编译镜像时,发现最后一直编译不过perf,具体的编译提示错误如下 ERROR: perf-1.0-r9 do_compile: oe_runmake failed ERROR: perf-1.0-r9 do_compile: Execution of /home/ub-1001/work/as66/imx8LBV…...

丹摩征文活动|详解 DAMODEL(丹摩智算)平台:为 AI 开发者量身打造的智算云服务
本文 什么是 DAMODEL(丹摩智算)?DAMODEL 的平台特性快速上手 DAMODEL 平台GPU 实例概览创建 GPU 云实例 储存选项技术支持与社区服务结语 在人工智能领域的飞速发展中,计算资源与平台的选择变得尤为重要。为了帮助 AI 开发者解决高…...
ORACLE _11G_R2_ASM 常用命令
--------查看磁盘组,(空间情况) select name,state,free_mb,total_mb,usable_file_mb from v$asm_diskgroup; --------查看磁盘情况 select GROUP_NUMBER,free_mb,total_mb,disk_number,MOUNT_STATUS,mode_status, HEADER_STATUS,name,PATH from v$asm_disk order …...
掌握Rust模式匹配:从基础语法到实际应用
本篇文章将探讨 Rust 编程语言中至关重要的特性之一——模式匹配。Rust 语言的模式匹配功能强大,不仅能处理简单的值匹配,还能解构和操作复杂的数据结构。通过深入学习模式匹配,程序员可以更加高效地编写出清晰、简洁且易于维护的代码。 Rus…...

HFSS 3D Layout中Design setting各个选项的解释
从HFSS 3D LAYOUT菜单中,选择Design Settings打开窗口,会有六个选项:DC Extrapolation, Nexxim Options, Export S Parameters, Lossy Dielectrics, HFSS Meshing Method, and HFSS Adaptive Mesh. DC Extrapolation 直流外推 直流外推分为标…...

线性表之链表详解
欢迎来到我的:世界 希望作者的文章对你有所帮助,有不足的地方还请指正,大家一起学习交流 ! 目录 前言线性表的概述链表的概述 内容链表的结构链表节点的定义 链表的基本功能单向链表的初始化链表的插入操作头插操作尾插操作 链表的删除操作头…...

C/C++使用AddressSanitizer检测内存错误
AddressSanitizer 是一种内存错误检测工具,编译时添加 -fsanitizeaddress 选项可以在运行时检测出非法内存访问,当发生段错误时,AddressSanitizer 会输出详细的错误报告,包括出错位置的代码行号和调用栈,有助于快速定位…...

【EI和Scopus检索】国际人工智能创新研讨会(IS-AII 2025)
国际人工智能创新研讨会(IS-AII 2025)将于2025年1月11日-1月14日在贵阳盛大举行。会议将聚焦计算机科学、人工智能、机器人科学与工程等相关研究领域,广泛邀请国内外知名专家学者,共同探讨相关学科领域的最新发展方向及行业前沿动…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...

VSCode 使用CMake 构建 Qt 5 窗口程序
首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...

【工具教程】多个条形码识别用条码内容对图片重命名,批量PDF条形码识别后用条码内容批量改名,使用教程及注意事项
一、条形码识别改名使用教程 打开软件并选择处理模式:打开软件后,根据要处理的文件类型,选择 “图片识别模式” 或 “PDF 识别模式”。如果是处理包含条形码的 PDF 文件,就选择 “PDF 识别模式”;若是处理图片文件&…...

【Qt】控件 QWidget
控件 QWidget 一. 控件概述二. QWidget 的核心属性可用状态:enabled几何:geometrywindows frame 窗口框架的影响 窗口标题:windowTitle窗口图标:windowIconqrc 机制 窗口不透明度:windowOpacity光标:cursor…...
iOS 项目怎么构建稳定性保障机制?一次系统性防错经验分享(含 KeyMob 工具应用)
崩溃、内存飙升、后台任务未释放、页面卡顿、日志丢失——稳定性问题,不一定会立刻崩,但一旦积累,就是“上线后救不回来的代价”。 稳定性保障不是某个工具的功能,而是一套贯穿开发、测试、上线全流程的“观测分析防范”机制。 …...