文章中其实有很多图来帮助理解,但是因为外链的原因,我电脑上的图不能直接拉过来,要完整版的可以评论我直接发PDF版本。因为笔记的原因没有英文注释代码,个人笔记,仅供参考。

排序

  • 排序
    • 排序算法的评估指标
    • 排序算法的分类
  • 插入排序
    • 算法效率分析
    • 优化——折半插入排序
  • 希尔排序(Shell Sort)
    • 算法性能分析
  • 冒泡排序
    • 算法性能分析
  • 快速排序
    • 算法效率分析
  • 简单选择排序
    • 算法性能分析
  • 堆排序
    • 堆的定义
    • 建立大根堆
    • 基于大根堆进行排序
    • 算法效率分析
  • 堆——插入删除
  • 归并排序(Merge Sort)
    • 算法效率分析
  • 基数排序(Radix Sort)
    • 算法效率分析
    • 基数排序的应用
  • 外部排序
    • 时间开销分析(二路)
    • 优化:多路归并
    • 优化:减少初始归并段数量
    • 多路平衡归并
  • 败者树
    • 败者树在多路平衡归并中的应用
  • 置换-选择排序
  • 最佳归并树
    • 多路归并的最佳归并树

排序

排序算法的评估指标

算法的稳定性:若待排序表中有两个元素RiR_iRi​和RjR_jRj​,其对应的关键字相同即keyi=keyjkey_i = key_jkeyi​=keyj​,且在排序前RiR_iRi​在RjR_jRj​的前面,若使用某一排序算法排序后,RiR_iRi​仍然在RjR_jRj​的前面,则称这个排序算法时稳定的,否则称排序算法是不稳定的。

排序算法的分类

  1. 内部排序:数据都在内存中——关注如何使算法时间、空间复杂度更低。
  2. 外部排序:数据太多,无法全部放入内存——还要关注如何使读/写磁盘次数更少。

插入排序

算法思想:每次将一个待排序的记录按其关键字大小插入到前面已排好序的子序列中,直到全部记录插入完成。

//直接插入排序
void InsertSort(int A[], int n){int i, j, temp;for(i=1; i<n; i++)                     //将各元素插入已排好序的序列中if(A[i] < A[i-1]){                   //若A[i]关键字小于前驱temp = A[i];                       //用temp暂存A[i]for(j=i-1; j>=0 && A[j]>temp; --j) //检查所有前面已排好序的元素A[j+1] = A[j];                   //所有大于temp的元素都向后挪位A[j+1] = temp;                     //复制到插入位置}
}

算法效率分析

空间复杂度O(1)O(1)O(1)

时间复杂度O(n2)O(n^2)O(n2)

算法稳定性:稳定

优化——折半插入排序

思路:先用折半查找找到应该插入的位置,再移动元素

当low>highlow > highlow>high时,折半查找停止,应将[low,i−1][low,\ i-1][low, i−1]内的元素全部右移,并将A[0]A[0]A[0]复制到lowlowlow所指位置。

当A[mid]==A[0]A[mid] == A[0]A[mid]==A[0]时,为了保证算法的“稳定性”,应继续在midmidmid所指位置右边寻找插入位置。

//折半插入排序
void InsertSort(int A[], int n){for i, j, low, high, mid;for(i=2; i<=n; i++){          //依次将A[2]~A[n]插入前面的已排列序列A[0] = A[i];                //将A[i]暂存到A[0]low = 1;                    //设置折半查找的范围high = i-1;while(low <= high){         //折半查找(默认递增有序)mid = (low + high) / 2;   //取中间点if(A[mid] > A[0])         //查找左半子表high = mid - 1;else                      //查找右半子表low = mid + 1;}for(j=i-1; j>=high+1; --j)A[j+1] = A[j];            //统一后移元素,空出插入位置A[high+1] = A[0];           //插入操作}
}

希尔排序(Shell Sort)

先追求表中元素部分有序,再逐渐逼近全局有序。

先将待排序表分割成若干形如L[i,i+d,i+2d,...,i+kd]L[i, i+d, i+2d,..., i+kd]L[i,i+d,i+2d,...,i+kd]的“特殊”子表,对各个子表分布进行直接插入排序。缩小增量ddd,重复上述过程,直到d=1d=1d=1为止。(每次将增量缩小一半)

//希尔排序
void ShellSort(int A[i], int n){int d, i, j;//A[0]只是暂存单元,不是哨兵,当j<=0时,插入位置已到for(d=n/2; d>=1; d=d/2)      //步长变化for(i=d+1; i<=n; ++i)if(A[i] < A[i-d]){       //需将A[i]插入有序增量子表A[0] = A[i];           //暂存再A[0]for(j=i-d; j>0 && A[0]<A[j]; j-=d)A[j+d] = A[j];       //记录后移,查找插入的位置A[j+d] = A[0];         //插入}//if
}

算法性能分析

时间复杂度:和增量序列d1,d2,d3...d_1,d_2,d_3...d1​,d2​,d3​...的选择有关,目前无法证明。

稳定性:不稳定

适用性:仅适用于顺序表,不适用于链表

冒泡排序

从后往前(或从前往后)两两比较相邻元素的值,若为逆序(即A[i−1]>A[i]A[i-1]>A[i]A[i−1]>A[i]),则交换它们,直到序列比较完。称这样的过程为“一趟”冒泡排序。

//交换
void swap(int &a, int &b){int temp = a;a = b;b = temp;
}//冒泡排序
void BubbleSort(int A[], int n){for(int i=0; i<n-1; i++){bool flag=false;              //表示本趟冒泡是否发生交换的标志for(int j=n-1; j>i; j--)if(A[j-1]>A[j]){swap(A[j-1], A[j]);flag = true;}if(flag == false)return;                     //本趟遍历后没有发生交换,说明表已经有序}
}

算法性能分析

空间复杂度:O(1)O(1)O(1)

时间复杂度:O(n2)O(n^2)O(n2)

快速排序

算法思想:在待排序表L[1...n]L[1...n]L[1...n]中任取一个元素pivot作为枢轴(或基准,通常取首元素),通过一趟排序将待排序表划分为独立的两部分L[1...k−1]L[1...k-1]L[1...k−1]和L[k+1...n]L[k+1...n]L[k+1...n],使得L[1...k−1]L[1...k-1]L[1...k−1]中所有元素小于pivot,L[k+1...n]L[k+1...n]L[k+1...n]中所有元素大于等于pivot,则pivot放在了其最终位置L(k)L(k)L(k)上,这个过程称为一次“划分”。然后分别递归地对两个子表重复上述过程,直至每部分内只有一个元素或空为止,即所有元素放在了其最终位置上。

//用第一个元素将待排序序列划分成左右两个部分
int Partition(int A[], int low, int high){int pivot = A[low];          //第一个元素作为枢轴while(low < high){           //用low、high搜索枢轴的最终位置while(low<high && A[high]>=pivot) --high;A[low] = A[high];          //比枢轴小的元素移动到左端while(low<high && A[low]<=pivot) ++low;A[high] = A[low];          //比枢轴大的元素移动到右端}A[low] = pivot;              //枢轴元素存放到最终位置return low;                  //返回存放枢轴的最终位置
}//快速排序
void QuickSort(int A[], int low, int high){if(low < high){int pivotpos = Partition(A, low, high);    //划分QuickSort(A, low, pivotpos-1);             //划分左子表QuickSort(A, pivotpos+1, high);            //划分右子表}
}

算法效率分析

每一层的QuickSort只需要处理剩余的待排序元素,时间复杂度不超过O(n)O(n)O(n)

时间复杂度:O(n∗递归层数)O(n* 递归层数 )O(n∗递归层数)

空间复杂度:O(递归层数)O( 递归层数 )O(递归层数)

稳定性:不稳定

把n个元素组织成二叉树,二叉树的层数就是递归调用的层数。

n个结点的二叉树: 最小高度 = ⌊log2n⌋+1\lfloor log_2n \rfloor + 1⌊log2​n⌋+1; 最大高度 = n

故:最好时间复杂度 = O(nlog2n)O(nlog_2n)O(nlog2​n)

​ 最坏时间复杂度 = O(n2)O(n^2)O(n2)

​ 最好空间复杂度 = O(log2n)O(log_2n)O(log2​n)

​ 最坏空间复杂度 = O(n)O(n)O(n)

可以得到结论,若每一次选择“枢轴”将待排序序列划分为均匀的两个部分,则递归深度最小,算法效率最高。

快速排序算法优化思路:尽量选择可以把数据中分的枢轴元素。

e.g.1 选头、中、尾三个位置的元素,取中间值作为枢轴元素

e.g.2 随机选一个元素作为枢轴元素

简单选择排序

每一趟在待排序元素中选取关键字最小的元素加入有序子序列。

//简单选择排序
void SelectSort(int A[], int n){for(int i=0; i<n-1; i++){          //一共进行n-1趟int min = i;                     //记录最小元素位置for(int j=i+1; j<n; j++)         //在A[i...n-1]中选择最小的元素if(A[j] < A[min]) min = j;     //更新最小元素位置if(min != i) swap(A[i], A[min]); //封装的swap()函数共移动元素3次}
}//交换
void swap(int &a, int &b){int temp = a;a = b;b = temp;
}

算法性能分析

空间复杂度:O(1)O(1)O(1)

时间复杂度:O(n2)O(n^2)O(n2)

稳定性:不稳定

适用性:既可以用于顺序表,也可用于链表

堆排序

堆的定义

若n个关键字序列L[1...n]L[1...n]L[1...n]满足下面某一条性质,则称为堆(Heap):

  1. 若满足:L(i)>=L(2i)L(i)>=L(2i)L(i)>=L(2i) 且 L(i)>=L(2i+1)(1<=i<=n2)L(i)>=L(2i+1)\ \ \ (1<=i<=\frac{n}{2})L(i)>=L(2i+1)   (1<=i<=2n​) ,则称为大根堆(大顶堆)

  2. 若满足:L(i)<=L(2i)L(i)<=L(2i)L(i)<=L(2i) 且 L(i)<=L(2i+1)(1<=i<=n2)L(i)<=L(2i+1)\ \ \ (1<=i<=\frac{n}{2})L(i)<=L(2i+1)   (1<=i<=2n​) ,则称为小根堆(小顶堆)

大根堆:完全二叉树中,根>=左、右

小根堆:完全二叉树中,根<=左、右

建立大根堆

思路:把所有非终端结点都检查一遍,是否满足大根堆的要求,如果不满足,则进行调整。

在顺序存储的完全二叉树中,非终端结点编号i<=⌊n/2⌋i<= \lfloor n/2 \rfloori<=⌊n/2⌋

检查当前结点是否满足根>=左、右,若不满足,将当前结点与更大的一个孩子互换。

若元素互换破坏了下一级的堆,则采用相同的方法继续往下调整。

//建立大根堆
void BuildMaxHeap(int A[], int len){for(int i=len/2; i>0; i--)    //从后往前调整所有非终端结点HeadAdjust(A, i, len);
}//将以k为根的子树调整为大根堆
void HeadAdjust(int A[], int k, int len){A[0] = A[k];                    //A[0]暂存子树的根结点for(int i=2*k; i<=len; i*=2){   //沿key较大的子结点向下筛选if(i<len && A[i]<A[i+1])i++;                        //取key较大的子结点的下标if(A[0] >= A[i]) break;       //筛选结束else{A[k] = A[i];                //将A[i]调整到双亲结点上k = i;                      //修改k值,以便继续向下筛选}}A[k] = A[0];                    //被筛选结点的值放入最终位置
}

基于大根堆进行排序

堆排序:每一趟将堆顶元素加入有序子序列(与待排序序列中的最后一个元素交换),并将待排序元素序列再次调整为大根堆(小元素不断“下坠”)。

基于“大根堆”的堆排序得到“递增序列”。

//建立大根堆
void BuildMaxHeap(int A[], int len);//将以k为根的子树调整为大根堆
void HeadAdjust(int A[], int k, int len);//堆排序的完整逻辑
void HeapSort(int A[], int len){BuildMaxHeap(A, len);           //初始建堆for(int i=len; i>1; i--){       //n-1趟的交换和建堆过程swap(A[i], A[1]);             //堆顶元素和堆底元素交换HeadAdjust(A, 1, i-1);        //把剩余的待排序元素整理成堆}
}

算法效率分析

一个结点,每“下坠”一层,最多只需对比关键字2次

若树高为h,某结点在第i层,则将这个结点向下调整最多只需要“下坠”h-i层,关键字对比次数不超过2(h-i)。

n个结点的完全二叉树树高h=⌊log2n⌋+1h = \lfloor log_2n \rfloor + 1h=⌊log2​n⌋+1

第i层最多有2i−12^{i-1}2i−1个结点,而只有第1~(h-1)层的结点才有可能需要“下坠”调整。

将整棵树调整为大根堆,关键字对比次数不超过
∑i=h−112i−12(h−i)=∑i=h−112i(h−i)=∑j=1h−12h−jj<=2n∑j=1h−1j2j<=4n\sum^1_{i=h-1}2^{i-1}2(h-i) = \sum^1_{i=h-1}2^i(h-i) = \sum^{h-1}_{j=1}2^{h-j}j <= 2n\sum^{h-1}_{j=1}\frac{j}{2^j} <= 4n i=h−1∑1​2i−12(h−i)=i=h−1∑1​2i(h−i)=j=1∑h−1​2h−jj<=2nj=1∑h−1​2jj​<=4n
∑j=1h−1j2j\sum^{h-1}_{j=1}\frac{j}{2^j}∑j=1h−1​2jj​是差比数列求和,用错位相减。

所以建堆的时间复杂度:O(n)O(n)O(n)

堆的调整需要时间复杂度:O(nlog2n)O(nlog_2n)O(nlog2​n)

堆排序的时间复杂度:O(n)+O(nlog2n)=O(nlog2n)O(n)+O(nlog_2n) = O(nlog_2n)O(n)+O(nlog2​n)=O(nlog2​n)

堆排序的空间复杂度:O(1)O(1)O(1)

稳定性:不稳定

堆——插入删除

对于小根堆,新元素放到表尾,与父结点对比,若新元素比父结点更小,则将二者互换。新元素就这样一路“上升”,直到无法继续上升为止。

被删除的元素用堆底元素替代,然后让该元素不断“下坠”,直到无法下坠为止。

归并排序(Merge Sort)

两个或多个已经有序的序列合并成一个。(“2路”归并

“2路”归并:设置三个指针i,j,ki,j,ki,j,k分别指向两个有序序列和一个将要存放归并序列的序列,对比i和j的大小,并存入k中,出和入的指针都加1。

其余路归并思想大致相同。

m路归并,每选出一个元素需要对比关键字m-1次,类似于冒泡挑出最值。

归并排序中,在内部排序中一般采用2路归并,先将每一个元素看作一路,两两相归并。

int *B = (int *)malloc(n*sizeof(int));    //辅助数组B//A[low...mid]和A[mid+1...high]各自有序,将两个部分归并
void Merge(int A[], int low, int mid, int high){int i, j, k;for(k=low; k<=high; k++)B[k] = A[k];                          //将A中所有元素复制到B中for(i=low, j=mid+1, k=i; i<=mid&&j<=high; k++){if(B[i] <= B[j])A[k] = B[i++];                      //将较小值复制到A中elseA[k] = B[j++];}while(i<=mid)A[k++] = B[i++];while(j<=high)A[k++] = B[j++];
}//用递归进行归并排序
void MergeSort(int A[], int low, int high){if(low < high){int mid = (low + high) / 2;   //从中间划分MergeSort(A, low, mid);       //对左半部分进行归并排序MergeSort(A, mid+1, high);    //对右半部分进行归并排序Merge(A, low, mid, high);     //归并}
}

算法效率分析

时间复杂度:O(nlog2n)O(nlog_2n)O(nlog2​n)

空间复杂度:O(n)O(n)O(n),来自于辅助数组B

稳定性:稳定的

基数排序(Radix Sort)

假设长度为n的线性表中每个结点aja_jaj​的关键字由d元组(kjd−1,kjd−2,kjd−3,...,kj1,kj0)(k^{d-1}_j,k^{d-2}_j,k^{d-3}_j,...,k^1_j,k^0_j)(kjd−1​,kjd−2​,kjd−3​,...,kj1​,kj0​)组成,其中,0≤kji≤r−10\le k^i_j\leq r-10≤kji​≤r−1,r称为“基数”。

基数排序得到递减序列的过程如下

初始化:设置r个空队列,Qr−1,Qr−2,...,Q0Q_{r-1}, Q_{r-2},...,Q_0Qr−1​,Qr−2​,...,Q0​

按照各个关键字位权重递增的次数(个、十、百),对d个关键字位分别做“分配”和“收集”

分配:顺序扫描各个元素,若当前处理的关键字位=x,则将元素插入QxQ_xQx​队尾

收集:把Qr−1,Qr−2,...,Q0Q_{r-1}, Q_{r-2},...,Q_0Qr−1​,Qr−2​,...,Q0​各个队列中的结点依次出队并链接。

基数排序不是基于“比较”的排序算法

基数序列通常基于链式存储实现。

算法效率分析

需要r个辅助队列,空间复杂度 = O(r)O(r)O(r)

一趟分配O(n)O(n)O(n),一趟收集O(r)O(r)O(r),总共d趟分配、收集,总的时间复杂度 = O(d(n+r))O(d(n+r))O(d(n+r))

稳定性:稳定的

基数排序的应用

统计学生的信息按年龄递减排序

权重:年 > 月 > 日

第一趟分配、收集(按“日”递增)

第二趟分配、收集(按“月”递增)

第三趟分配、收集(按“年”递增)

基数排序擅长解决的问题:

  1. 数据元素的关键字可以方便地拆分为d组,且d较小
  2. 每组关键字的取值范围不大,即r较小
  3. 数据元素个数n较大

外部排序

数据元素太多,无法一次全部读入内存进行排序。

使用“归并排序”的方法,最少只需在内存中分配3块大小的缓冲区即可对任意一个大文件进行排序。

  1. 构造初始“归并段”,在输入缓冲区1和输入缓冲区2排好两块的序,然后通过输出缓冲区写入磁盘;

  2. 第一趟归并;

  3. 第二趟归并;

  4. …直到所有数据被归并完毕,得到完整的排序。

时间开销分析(二路)

外部排序时间开销 = 读写外存的时间 + 内部排序所需时间 + 内部归并所需时间

读写磁盘次数 = 文件总块数*2 + 文件总块数*2*归并趟数

故优化方法可以减少归并趟数

优化:多路归并

重要结论:采用多路归并可以减少归并趟数,从而减少磁盘I/O(读写)次数。

对rrr个初始归并段,做kkk路归并,则归并树可用kkk叉树表示

若树高为hhh,则归并趟数 = h−1h - 1h−1 = ⌈logkr⌉\lceil log_kr\rceil⌈logk​r⌉

推导: kkk叉树第hhh层最多有kh−1k^{h-1}kh−1个结点,则r≤kh−1r\le k^{h-1}r≤kh−1,(h−1)最小=⌈logkr⌉(h-1)_{最小}=\lceil log_kr\rceil(h−1)最小​=⌈logk​r⌉

多路归并带来的负面影响:

  1. k路归并时,需要开辟k个输入缓冲区,内存开销增加;
  2. 每挑选一个关键字需要对比关键字(k - 1)次,内部归并所需时间增加。

优化:减少初始归并段数量

由 归并趟数 = h−1h - 1h−1 = ⌈logkr⌉\lceil log_kr\rceil⌈logk​r⌉可得:

当r减小时,归并趟数也会减小

多路平衡归并

k路平衡归并:

  1. 最多只能有k个段归并为1个;
  2. 每一趟归并中,若有m个归并段参与归并,则经过这一趟处理得到⌈m/k⌉\lceil m/k \rceil⌈m/k⌉个新的归并段。

败者树

可视为一棵完全二叉树(多一个头)。k个叶结点分别时当前参加比较的元素,非叶子结点用来记忆左右子树中的“失败者”,而让胜者往上继续进行比较,一直到根结点。

败者树在多路平衡归并中的应用

对于k路归并,第一次构造败者树需要对比关键字k-1次

有了败者树,选出最小元素,只需对比关键字⌈log2r⌉\lceil log_2r\rceil⌈log2​r⌉次

置换-选择排序

老的方法:用于内部排序的内存工作区WA可容纳lll个记录,则每个初始归并段也只能包含lll个记录,若文件共有nnn个记录,则初始归并段的数量r=n/lr = n / lr=n/l

使用置换-选择排序,可以让每个初始归并段的长度超越内存工作区大小的限制

最佳归并树

重要结论:归并过程中磁盘I/O次数 = 归并树的WPL(weight path length)*2

要让磁盘I/O次数最少,就要使归并树WPL最小——哈夫曼树!

多路归并的最佳归并树

k路归并也是用哈夫曼树,每层k个结点。

注意:对于k叉归并,**若初始归并段的数量无法构成严格的k叉归并树,则需要补充几个长度为0的“虚段”,**再进行k叉哈夫曼树段构造。

补充“虚段”:

  1. 若(初始归并段数量-1) % (k-1) = 0,说明刚好可以构成严格k叉树,此时不需要添加虚段;
  2. 若(初始归并段数量-1) % (k-1)= u ≠\ne​= 0,则需要补充(k-1)- u 个虚段。

数据结构——排序 笔记合集(C语言)完结相关推荐

  1. 【KnowingAI知智】S4语音任务|知识卡片|笔记合集

    KnowingAI知智-S4语音任务 本文系笔者在观看B站up主@KnowingAI知智的S4系列短视频所做的笔记合集 原视频见S4语音任务 S4E0:声音与机器 语音任务和自然语言处理相比,其更加纯 ...

  2. java入门笔记合集(杂乱)(2)

    java入门笔记合集(杂乱)2 StringBuilder 这是一个容器,可以和String搭配起来用 package day1;import java.util.Scanner;public cla ...

  3. 视频教程-Go语言实战合集-Go语言

    Go语言实战合集 毕业于清华大学,曾担任Google算法工程师,微软区块链领域全球最具价值专家,微软Tech Ed 大会金牌讲师. 精通C/ C++,Python ,Go语言,Sicikit-Lear ...

  4. NLP论文笔记合集(持续更新)

    NLP论文笔记合集(持续更新) 经典论文 参考文献 情感分析论文 关键词 综述 参考文献 非综述 参考文献 其他论文 参考文献 经典论文 2003年发表的文章1^11,NLP经典论文:NNLM 笔记 ...

  5. Python学习笔记合集(总结)

    Python学习笔记合集(总结) 第一天主要讲了Python基本语句(上) 注释 输出 标识符 多行语句 第二天主要讲了Python基本语句(下) 行与缩进 关键字 数据类型 第三天主要讲了impor ...

  6. 【FFT夯实基础系列】手写笔记合集|傅里叶级数、傅里叶变换

    B站up主@mazonex推出的宝藏系列视频课笔记 因为是数学类的,所以笔者采用了手写并导出的形式 这一篇合集包括了up主[傅里叶夯实基础系列]视频的P1-P6,可以通过上方链接看具体视频 目录 傅里 ...

  7. PHP代码审计入门笔记合集(共20篇)

    早安,我的朋友们. 今天是11月20号,离2021年只41天了,今年你的小目标完成了吗? 跟大家分享件事情,其实这几个月来,我一直在准备一场考试,值得高兴的是,就在前两天终于顺利通过CISSP考试,完 ...

  8. (小甲鱼python)集合笔记合集一 集合(上)总结 集合的简单用法 集合的各种方法合集:子、交、并、补、差、对称差集、超集

    一.基础复习 集合与字典区别 集合中所有元素都是独一无二的,并且也是无序的. 集合具有唯一性.无序性.有限性 >>> type({}) #字典 <class 'dict'> ...

  9. 2021-10-16【严蔚敏数据结构代码实现合集】【c语言学习必备】

    本文记录了我为期三个月<算法与数据结构>的学习历程,仅作为记录自己学习状态的文章. 线性表 2021-9-14[数据结构/严蔚敏][顺序表][代码实现算法2.1-2.7] 2021-9-1 ...

最新文章

  1. 可视化的Redis数据库管理工具redis-desktop-manager的初步使用(图文详解)
  2. python 下载网页文件_『如何用python把网页上的文本内容保存下来』python爬取网页内容教程...
  3. centos下实现程序开机自启动(tomcat为例)
  4. 隐马尔科夫模型-EM模型-混合理解
  5. Mysql升级过程的问题
  6. 02-JDBC学习手册:JDBC编程步骤【重点重点】
  7. 桌面快速启动软件AltRun----赶快使得你的桌面变整洁吧
  8. 带你全面了解Http和Https
  9. 交付方式 saas_扩展和交付SaaS启动的最佳方法
  10. 提高语音识别率:必须加入深度学习吗?
  11. Quartz.NET 学习相关博客
  12. Kettle下载安装使用
  13. libcrypto yum 安装_centos7下nginx 报错需要安装 libcrypto.so.10(OPENSSL_1.0.2)(64bit)
  14. 设置ubuntu终端光标开启自动显示
  15. 科大讯飞输入法android离线语音,讯飞输入法Android5.0.1752 离线语音更轻快的表达...
  16. 洞悉物联网发展1000问之为什么虚拟现实技术将迎来春天?
  17. Python 黑马程序员 笔记
  18. kafka-分区重分配及相关源码分析
  19. 机器学习-33-Anomaly Detection(异常侦测)
  20. java8 使用stream进行排序(多字段排序、升序、降序)

热门文章

  1. 以太网OAM和CFM的基本概念、配置和应用
  2. Tile Forward Shading
  3. MyBatis-一级缓存与二级缓存
  4. in作为介词的用法_英语当中介词in的用法
  5. Swift成为主流语言的10个理由
  6. 计算机组装与维护贴吧,试论《计算机组装与维护》的教学改革
  7. 单精度浮点数加法器电路设计
  8. c266 设置邮箱_C226机器设置ip-C226-柯尼卡美能达(查看)
  9. 报考指导:盘点985高校中的20所“精英大学”
  10. 如何修改安卓界面上的图片和文字