自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(47)
  • 收藏
  • 关注

原创 选择排序之简单选择排序

简介基本思想:在待排序数据中,选择最大或者最小的元素放在其最终位置基本操作:实例:从序列中选择一个出一个最小的元素,然后将最小元素与第一个位置元素交换位置8的位置确定后,不需要做调整了,然后在剩下的序列中,找到第二小的元素,放在第二个位置:16的位置也不需要做调整了,然后在剩下的序列重复找第三小,第四小…最终排序完成,整个过程就是选择第n小的元素,放在第n号下标中。代码:void SelectSort(int array[], int length){ int min;

2021-05-23 17:03:50 129

原创 交换排序之快速排序

特点选取一个中心或者基准,一般选择第一个。然后将比基准大的元素搬到后面,比基准小的元素搬在后面,此时基准左边的元素(左子表)都小于基准,右边的元素(右子表)都大于基准。然后将左子表继续按照上述步骤进行操作,选取新基准,小的在前,大的放后。右边的序列相同。直到序列的长度为1时,结束操作。整个过程是一个递归的思想,递归结束条件是子序列长度为1。基本思想:通过一趟排序,将排序记录分割成独立的两部分,其中一部分记录的比另一部分关键字小,则可对这两部分记录进行排序,以达到整个序列有序。具

2021-05-23 16:15:56 252

原创 交换排序之冒泡排序

特点挨个比较,如果发生逆序,就交换两个元素的位置。实例代码void print(int *arr,int length){ for(int i =0;i<length;++i){ std::cout<<arr[i]<<" "; } std::cout<<std::endl;}void BubbleSort(int *arr,int length){ int i,j; for(i = 0;

2021-05-22 21:31:15 138

原创 插入排序之希尔排序

特点基本思想:将整个待排序列分割成若干子序列,分别进行直接插入排序,待整个序列中记录“基本有序”时,再对全体记录进行一次直接插入排序。首先定义增量序列,如 下图,5,3,1,增量是递减的,并且最终一定要做一次增量为1的插入排序增量为5:对于间隔为5构成的序列进行插入排序增量为3:对于间隔为3构成的序列进行插入排序增量为1:对整体进行直接插入排序且增量与增量之间应互为质数。实例增量(间隔)为5时,分成5个子序列:分别是{81,35,41},{94,17,75},{11,95,15},{

2021-05-22 20:46:51 1046 2

原创 插入排序之折半插入排序

特点折半插入排序:用二分查找的方法在有序部分找到待排序元素插入的位置,叫做折半插入排序实例代码void BinaryInsertSort(int *arr,int length){ int i; //无序部分第一个元素 int j; //有序部分插入位置下标的前一个位置 int low; int high; int mid; for(i = 2;i<=length;++i){ //初始状态arr[1]是有序的,所以i从2开始比较

2021-05-22 17:07:33 548

原创 插入排序之直接插入排序

特点直接插入排序:顺序遍历有序的部分元素去找到待排序元素插入的位置,叫做直接插入排序基本过程:将一个待排序的数组分为2部分,第一部分是arr[1]有序部分,第二部分是arr[1]~arr[length-1]无序部分arr[0]是一般被赋值为待排序元素 ,作为哨兵位每次从无序部分抓取一个元素即arr[i],从后往前或者从前往后与有序部分元素进行比较大小,将该元素插入到合适的位置直到最后无序部分都加入到了有序的队伍里,完成排序.实例每次将arr[0] = arr[i]从后往前移动j,比较ar

2021-05-22 16:45:20 309

原创 查找算法之分块查找

基本思路按照表的特点,将表分为几部分或者几块,需要查找元素key时,我们确定好元素在哪个块,然后再去对应的块中进行查找,根据块内数据的特点,再去选择顺序查找还是二分查找。实例将表分为三个部分,第一个部分最大值为22,第二个部分最大值为48,第三个部分最大值为86。然后建立一个索引表,分别记录每块的最大值以及最大值块部分的起始地址。查找时:查找所在块时,可以使用二分查找在快内进行查找时,根据数据有无序,进行二分或者顺序查找...

2021-05-22 09:50:01 721

原创 线性表查找之二分查找(折半、对分查找)

特点:前提是对有序的一组元素进行查找每次将待查记录所在区间缩小一半代码:不断的缩小范围:#include <iostream>#include <assert.h>using namespace std;int binary_search(int key,int *arr,int length){ assert(arr != NULL); assert(length > 0); int low = 0; int high

2021-05-22 09:27:31 658

原创 关于顺序表查找效率提升的讨论

上一篇文章,顺序表的查找数据元素查找概率不相等时如何提高查找效率对于查找概率比较多的元素(事先知道查找概率),放在靠后的位置,从后向前查找时,更快找到:被查找概率越高,比较次数越少被查找概率越低,比较次数较多事先不知道元素的查找概率空间换时间的思想:元素不光是元素数据本身了,再添加一个域来记录当前数组的访问频度或者访问次数这个过程始终的去保持访问频度较高的在顺序表后,这个过程需要去动态的调整...

2021-05-21 22:24:06 986

原创 查找算法之顺序查找以及设置哨兵位进行改良

应用范围顺序表或线性链表表示的静态查找表表内元素之间是无序的顺序表的定义struct Table{ ElemType *arr; //表基址 int size; //表中元素的个数};Table tb;在顺序表tb中查找值为key的元素,size == 11,capaticy == 12,0号元素存放需要查找的key值可以从前往后找:intfind(int key,int *arr,int size){//第一次比较 i<=sizefor(int i =1;i <

2021-05-21 22:02:24 1707

原创 Linux上使用cmake构建工程时用ccache来加速编译

安装sudo apt-get install ccache使用 ccache_path=`command -v ccache` if [ -n "$ccache_path" ];then export CXX="$ccache_path g++" export CC="$ccache_path gcc" fi

2021-05-17 22:04:51 1906

原创 cmake指定第三方的编译器以及指定当前系统中的同类型不同版本的编译器

cmake指定编译器:set(TOOLCHAIN "/opt/psdk/gcc-arm-aarch64-none-linux-gnu")#指定C编译器set(CMAKE_C_COMPILER "${TOOLCHAIN}/bin/aarch64-none-linux-gnu-gcc")#指定C++编译器set(CMAKE_CXX_COMPILER "${TOOLCHAIN}/bin/aarch64-none-linux-gnu-g++")这个在交叉编译中经常使用到,使用cmake构建工程时,需要

2021-05-17 21:58:21 1001

原创 二叉树的存储结构顺序存储和链式存储

顺序存储实现:将一棵二叉树按照当做一棵满二叉树进行编号(从上到下,从左到右),编号作为数组的下标,一次存放到二叉树的数据元素。当一个二叉树不是完全二叉树,那么总会有一些位置没有元素,那么就将这些位置空出来。#define CAPACITYtypedef TElemType SqBinaryTree[CAPACITY];SqBinaryTree sb;将下表恢复成一棵二叉树:如图,空着的地方对应没有数据:缺点:浪费储存空间,只有左孩子或者只有右孩子的情况更加明显,更适用于满二叉树或者

2021-05-16 14:41:14 2973

原创 二叉树的性质与满二叉树和完全二叉树

性质一:二叉树中,第i层上至多有2^(i-1)个结点(i>=1):至少需要有一个结点,否则就不存在这一层了。性质二:深度为k的二叉树至多有(2^k) -1个结点(k>=1):实际上是等比数列的求和:2^0 + 2^2 + 2^3 + … + 2^k-1 = = (2^K) -1性质三:对于任何一棵二叉树T,如果其叶子结点数为n0,度为2的结点数为n2,那么n0 = n2+1比如满足上图:叶子结点数: 7 8 9 10 11 12度为2结点数:1 2 3 4 5满二叉树:根据

2021-05-16 13:49:58 1630

原创 树的基本概念与二叉树的定义

树的概念:根结点:A,即唯一一个没有前驱的节点结点的度:也叫结点的子树的个数,比如A结点的度是3,分别是B C D, C结点的度是1,只有G树的度:所有结点的度的最大值,这里最大为3,A或者D的度最大叶子结点:无后继的结点,也叫终端结点双亲和孩子结点: BCD的双亲是A,A的孩子结点是BCD兄弟结点: 双亲结点相同的节点,如H I J的双亲结点都是D,所以H I J是兄弟结点堂兄弟结点:位于同一层上的节点为堂兄弟结点,比如E F G H I J ,因为他们的双亲结点是在同一层的树的深度:树

2021-05-15 21:37:15 256 1

原创 linux上如何分辨一个二进制可执行文件是debug还是release的

假设,我们可执行文件是a.out:readelf -S a.out | grep debug如果,该文件是debug的,则会打印出类似这样的信息: [29] .debug_aranges PROGBITS 0000000000000000 00003042 [30] .debug_info PROGBITS 0000000000000000 000030d2 [31] .debug_abbrev PROGBITS

2021-05-15 20:52:46 2283

原创 gdb使用list查看源码不显示的问题

debug版本的可执行文件中保存的是源码文件的路径,当我们将可执行文件移动到其他环境的话,就无法根据该路径查看对应的源码文件了,所以看不到。

2021-05-15 20:46:48 1053

原创 Linux网络编程之端口复用 Address already in use

为什么需要端口复用我们直到,TCP连接在进行4次挥手断开连接时,为了确保最后一次ACK到达对端,保证对端正确关闭资源,以防止对傻傻等待浪费网络和计算机资源,要求等待2MSL时常,那么对于我们需要立即重启程序的情况不友好,有过经验的朋友都知道,我们关闭一个链接,然后立马重启这个连接,一般会报bind失败:虽然这个图是客户端主动断开连接,实际服务端主动断开也是一样的过程bind error: Address already in use表示端口号正在被占用,因为前一次的链接还没有被完全释放,通过指令可

2021-05-10 07:41:20 309

原创 IO多路转接epoll函数解析复习

函数原型:open an epoll file descriptor: 打开一个epoll文件系统#include <sys/epoll.h>int epoll_create(int size);参数:在内核中开辟一块内存,创建一个epoll文件系统(也叫内核事件表、是一棵红黑树),参数size是对内核的一个建议,但是一定要比0大,不一定起作用,表示监听的文件描述符个数,也就是基础红黑树的建议大小。返回值:ret > 0 返回一个可用,合法的文件描述符,表示创建的epo

2021-05-09 17:38:38 140

原创 IO多路转接之poll函数解析

函数原型:#include <poll.h>int poll(struct pollfd *fds, nfds_t nfds, int timeout);返回值:ret > 0 ,表示有事件发生的文件描述符的个数,可以去遍历fds,看哪个fd发生事件,并且根据对应的revent做下一步处理ret == 0,表示超时,且还没有事件发生ret<0,表示失败,可以根据全局变量errno来判断下一步的动作参数解析:struct pollfd *fds:是一个数组,将所有

2021-05-09 14:33:27 372

原创 数据结构与算法之排序方法分类

按照存储介质分内部排序:数据量不大,数据都在内存中,无需内外存进行交换数据外部排序:数据量较大,数据在外存,排序时需要将数据换入换出内存按比较器个数分串行处理:单处理机 同一时刻比较一对元素并行处理:多处理机 同一时刻比较多对元素按主要操作分比较排序:用比较的方法,如插入排序,交换排序,选择排序,归并排序基数排序:不比较元素的大小,仅仅根据元素本身的取值确定其有序的位置按照排序所需辅助空间可分为:原地排序:空间复杂度为O(1),空间复杂度不会随着数据量的增大而增大非原地排序:超过O(1

2021-05-07 08:08:39 235

原创 OS内存管理之页面置换

前面讲到,我们需要将一些页面加载到内存,此时刚好内存上没有可用的物理内存编号,这个时候就需要将一些页面置换到磁盘让出位置。置换的基本策略:置换最近不可能访问的页根据局部性原理,基于过去的行为来预测将来的行为。策略设计太简单,实行起来可能会很低效,如果过于精密和复杂,软硬件开销也会更大,一般需要折中。页框锁定:一些页框是绝对不允许被置换出去的,否则会出错或者影响效率,如:操作系统核心代码关键数据结构正在进行IO操作缓冲区等我们需要将这些页面锁定,不让操作系统对这些页面进行置换或者延迟进

2021-05-06 23:13:15 150

原创 基本内存管理方案2---一个进程进入内存中若干不连续的区域(页式,段式,段页式)

页式设计思想:将用户进程地址空间划分为大小相等的页、页面(一般为4K,也有4M的),并从0开始编号将物理内存地址空间划分为大小相等的区域,称为页框,也从0开始编号,也叫做物理页面,页帧,内存块以页为单位进行分配,按照进程所需要的页数来分配,进程地址空间上相邻的页,映射到物理内存上,页不一定相邻。**逻辑地址:**页号(20,页面的编号) + 页内地址(也叫页内偏移,12位)页表:记录了逻辑空间某页面对应在物理地址空间上是哪一页页表项:页表的每一行称为页表项,记录逻辑页号和物理页号的对应关系

2021-05-06 22:37:22 327

原创 OS内存管理之虚拟存储技术

概念:当进程运行时,先将其一部分数据和代码装入内存,另外一部分暂留在磁盘,当要执行的指令或者访问的数据不在内存时,由操作系统自动完成将它们从磁盘上调入内存中运行。注意:与交换技术不同,交换技术是将某一个进程换入换出,这里虚拟存储技术换入换出的粒度更加小了。虚拟地址空间:给进程分配的虚拟内存虚拟地址:虚拟内存上数据或者指令的地址,该位置可以被访问,仿佛就是内存的一部分。虚拟内存在哪里:把内存与磁盘有机的进行结合起来使用,从而得到一个容量很大的"内存",即虚拟内存虚拟内存是对内存的抽象,建立在金

2021-05-06 22:33:56 281

原创 OS内存管理之Page fault

可能产生异常的情况:需要的访问虚拟页面没有调入内存 — 缺页异常页面访问违反权限错误的访问地址…缺页异常处理主要过程:产生异常操作系统调用异常处理程序获取磁盘地址启动磁盘将该页调入内存:内存有空闲页框,分配,然后直接调入该页面;内存没有空闲页框,将内存中的某个不常用的页框置换出去(需要看具体的页面置换算法),检查该置换页面是否被修改过,如果修改过需要写入磁盘如果没有修改,直接调换出去,将我们需要加载的页面调进内存。...

2021-05-06 22:26:54 177

原创 OS内存管理之快表(TLB)的引入

在前面的文章中,讲到操作系统的多级页表映射:多级页表文章背景我们知道,要从虚拟地址转换成一个物理地址,需要访问多次内存查页表,比如2级页表,需要访问2次内存,4级页表,查询需要访问4次内存,这也是一笔不小的开销,这样会让CPU真正执行指令的时间缩短,导致CPU的超高速度优势利用不充分。快表应运而生原理:程序访问的局部性原理,对于一些指令和数据访问,在一段时间内总是高度的频繁本质:Translation Look-aside Buffers实际上就是一个缓冲区,实际上是CPU的高速缓存,可以缓解

2021-05-06 22:15:27 732

原创 OS内存管理之页表,页表项以及页目录

页表由多个页表项组成,即页表中每一行的就是一个页表项。页表项中记录的信息:页框号:记录虚页面对应的具体哪个物理页面有效位:标识该页表项对应的虚页面有没有读进内存,否则在磁盘访问位:引用位,标识该页面有没有被访问过修改位:此页面在内存中有没有被修改过,如果被修改过,将来是要被持久化到磁盘上的,该标志位就是这个目的保护位:标识该页面的读写等权限页表项一般是由硬件设计的,因为地址转换时大多数是由硬件完成的。引出页目录:对于32位虚拟地址空间,假设页面大小为4K,页表项大小为4字节:一个进程

2021-05-06 21:47:27 4779

原创 OS内存管理之交换技术

产生背景:进程的地址空间大于物理地址空间,即在较小的内存空间运行较大的进程。内存"扩充"技术:1.内存紧缩技术(可变分区)可变分区概述2.覆盖技术:根据程序的逻辑来选择,一些段永远不会同时出现在内存中,假设有段A和段B,他俩永远不会同时加载到内存上运行,那么A和B就可共享某一段物理内存,进行交替的使用物理内存。这就需要程序员显式的声明覆盖结构,比较老的技术了,适用于早期的某些操作系统。3.交换技术:虚拟内存的初步设计,当内存空间紧张时,系统将一些进程暂时移动到外存,把外存中某些进程换进内

2021-05-06 07:48:58 707

原创 基本内存管理方案1---整个进程进入内存的一片连续的区域

单一连续区一段时间内,只有一个进程在内存内优点:简单缺点:内存利用率低固定分区把内存空间先分割成若干区域,称作为分区。每个分区的大小可以相同,也可以不同一旦确定,分区大小固定不能变了每个分区装一个且只能装一个进程进程装载时,根据自身所需空间大小,向操作系统进行申请,然后去相应合适分区进行排队。可变分区根据进程的需要,把内存空闲空间分割出一个分区,分配给该进程,剩余的部分成为新的空闲分区运行一段时间后,可能造成下列布局:缺点:造成大量的内存碎片(外碎片)解决方案:碎片紧缩

2021-05-05 21:38:05 215

原创 Linux伙伴系统内存分配原理概述

简介:Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担.,该算法由Knowlton设计, 后来Knuth又进行了更深刻的描述.核心思想:将内存按2的幂进行划分,组成若干空闲链表;查找该链表找到能满足进程需求的最佳匹配块。算法基本步骤:将整个可用的内存空间看做一个整体,大小为: 2^u(2的u次方)假设现在一个进程申请的空间为s:如果满足2^(u-1) < s <= 2^u,那么就将这整块内存分配给该进程否则,就将这

2021-05-05 19:19:26 999 1

原创 C++STL容器迭代器失效问题

本文拿std::vector来举例说明,什么是迭代器失效:拿两个代码片段来说明迭代器失效现象:int main(){ vector<int> vec; for(int i = 0;i < 20 ;++i){ vec.push_back(rand()%100); } //打印一下 for(const int v:vec){ std::cout<<v<<" "; } std::c

2021-05-04 21:11:36 361

原创 C++运算符重载中有些方法为什么需要定义为友元函数

C++提供运算符重载主要目的:希望对象之间的运算看起来可以和编译器内置类型一样丝滑;相当于是告知编译器,类对象之间运算应该如何去做处理。通过实现一个复数类,来阐述本文章的主题:class Complex{public: Complex(int r = 1,int i = 1):real_(r),image_(i){} ~Complex(){} void print(){ std::cout<<"real_= "<<real_&lt

2021-05-04 17:12:54 2444 2

原创 TCP可靠传输的实现

TCP基于以字节为单位的滑动窗口来实现可靠传输

2021-05-03 22:08:14 90

原创 TCP连接的建立与释放过程

TCP连接需要解决的问题需要让通信双方能感知到对方的存在过程中需要协商一下一些参数,如最大窗口值,时间戳选项,服务质量等双方能够对运输实体资源(如数据缓存大小,连接表中的项目等)进行分配三次握手的具体过程:能否使用2次握手:不行这里假设2次握手后,双方就处于连接建立状态:ESTABLISHED客户端向服务端发送连接建立请求报文A,但是A报文由于某些原因在网络中滞留超时客户端超时重传请求报文B,此时报文B到达服务端,服务端返回报文B的确认报文此时双方建立连接,然后进行数据传输,数据传

2021-05-03 22:07:41 692

原创 TCP超时重传时间的选择

RTT:假设A向B发送数据,我们将A的数据发送出去到A收到B的确认报文的这段时间就成为RTT时间。超时重传时间(RTO)的选择:1.假设选择RTO小于RTT时间:假设A向B发送数据,此时网络正常,没有发生异常,还没等一个RTT时间到,也就是B给A的确认报文还在网络上正常传输呢,超时重传定时器就到期了,造成分组的重传,不必要的分组在网络越来越多,影响网络整体的性能。2.假设选择RTO比RTT大的比较多呢:假设A向B发送数据,此时网络有点波动,导致报文B向A确认的报文丢了,然后A等了很久,超时定时器

2021-05-03 20:59:33 750

原创 TCP的拥塞控制

网络拥塞:网络中的输入,超出了某一网络资源(交换节点缓存,处理机,带宽等等都是)所能提供的服务的能力,网络性能就会变差,大量数据分组被丢弃,直观感受是变卡。如果不对网络拥塞进行控制,整个网络吞吐量会不断的随数据输入而下降。四种拥塞控制算法:拥塞窗口是多少,就能发送几个报文段。慢开始即一开始向网络注入的报文少一些,假定这里的ssthresh = 16.即刚开始将cwnd值置为1:此时只能发送一个报文,收到B的确认报文后cwnd = cwnd +1此时cwnd = 2,给B继续发送2个报文,

2021-05-03 20:34:45 225 1

原创 TCP的流量控制---滑动窗口

流量需要控制的原因:发送方发送太快,接收方来不及接收,导致数据的丢失,引起性能下降。流量控制:让发送方发送效率不要太快,要让接收方来得及接收,整个过程是接收方(接收窗口)和发送方(发送窗口)一个动态协商的过程。滑动窗口机制A对B发送数据,B需要对A进行流量控制,B主机告诉A最多能接收几个窗口的数据,主机A会调整相应发送窗口大小。整个过程中,经过B确认收到后的数据,A可以直接将自己缓存的部分进行删除,移出滑动窗口,,如果没有收到B的确认,否则不能删除,万一出现差错,数据还需要重新发送给B。持续

2021-05-03 16:59:54 342

原创 运输层TCP与UDP的区别

运输层端口号:标识通信进程端口号屏蔽了不同操作系统上的进程不同实现的差异,取值范围0-65535熟知端口号:0-1023,FTP:21/20 HTTP:80 DNS:53登记端口号:1024-49151短暂端口号:49152-65535,留给客户进程选择暂时使用,标识了主机上进行通信的一个进程面向连接的TCP:TCP报文段必须先进行三次握手逻辑连接,结束通信需要四次挥手释放逻辑连接;TCP仅支持单播,即一对一通信;面向字节流的,无规则无边界;不会出现传输差错,误码,丢失,乱

2021-05-03 16:33:26 188

原创 路由选择协议

静态路由配置人工的通过一些指令设置网络所需的路由表,适用于一些比较小的网络结构中。动态路由配置通过一些算法,自动调整更新路由表,能较好的适应网络状态的变化。因特尔分层路由选择协议常见的路由选择协议...

2021-05-02 22:20:32 138

原创 IP数据报的发送和转发过程

源主机如何判断目标地址在不在同一个网络中:假设主机C要给F发送数据,主机C用自己的ip地址和子网掩码进行相与得出主机C所在网络的网络地址主机C再用主机F的ip地址与当前的子网掩码相与得出得出主机F所在网络的网络地址如果这两个值相同,可以证明在一个网络中,直接交付即可。如果值不同,则说明没有在同一网络,需要间接交付,通过路由器的转发。直接交付间接交付:需要通过路由器进行转发期间,如果报文出错,会向源主机发送ICMP差错报文主机C如何知道向哪个路由器发送数据呢?默认网关,这里指的是接口0

2021-05-02 22:06:30 1389

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除