自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 生产消费者模型

不过,为了维持生产消费者模型的正常运转,生产者和消费者之间也要存在同步关系,亦即相互之间根据彼此的状况对自身进行调整,否则,会出现供大于求的情况,导致冗余问题,或者供小于求的情况,导致饥饿问题。(1)解耦:对于一个普通的函数而言,其按部就班的从上到下运行,不过当涉及一个函数调用的时候,从调用这个函数、把参数传递给这个函数、再到这个函数把运行结果返回给主程序,在这段过程中,主程序是什么都不能做的,只能卡在那里,等待处理结果,这就会浪费很多时间。所以生产者之间是互斥的,而互斥的关系需要通过加锁来维持正常运转。

2022-09-02 09:54:14 547 1

原创 死锁的成因及避免

对于死锁,形象的描述就是两个人都抓着对方,A说:B你放手我就放手,B说:A你先放手我再放手,于是两个人就僵持不下,形成死锁。:当一个进程请求资源失败的时候,不会继续保持自己的资源,而是把自己的资源释放。:如果一个进程申请资源失败的时候,它不会放弃自己原有的资源,而是在保持原有资源的前提下对其申请的资源进行等待。:一个资源只能被一个进程调用,在该资源被调用的同时,其它进程是不能使用该资源的,只能等待。:破坏环路形成的条件,让不同的进程尽可能的按顺序申请资源。:一个进程请求资源,对方不给,可以抢过来。...

2022-09-01 10:48:34 243

原创 如何创建和删除一个可执行文件

具体来讲,文件的属性信息存储在inode中,亦即想要创建一个可执行文件,首先就需要申请一块inode空间,具体方式就是遍历inode bitmap,找到其中为0的位,亦即可以拿来使用的位,将其置为1,这样的操作过后,该位上的inode空间就属于这个文件了。接下来需要做的是写入文件的具体信息,那就需要为当前只有属性信息的文件申请一块存储具体信息的空间,申请空间的具体方式和上面一样,也是遍历位图。作为一个文件,软链接保存的是其所对应文件的路径,所以软链接实际上起到某个文件快捷方式的作用。...

2022-09-01 10:06:27 431

原创 进程的状态

在睡眠状态的基础上引入深度睡眠状态的原因是,常规的可中断的睡眠状态是可能存在问题的,当一个进程在内存中运行时,如果需要数据,会向硬盘提出要求,在等待数据的时候,这个进程就会进入睡眠状态。孤儿进程: 相比于僵尸进程是子进程先退出,父进程后退出,孤儿进程是父进程已经退出了,但子进程仍在运行。僵尸进程:当一个子进程退出的时候,父进程理应回收其退出状态等相关信息,但是有些时候父进程正在处理其它事情,无暇读取子进程的退出状态,这时子进程就会变为僵尸进程,保持其基本的退出信息,等父进程运行完了再来读取。...

2022-08-31 12:23:00 685

原创 内核态和用户态

(3)在对信号处理完毕之后,进程理应当是返回用户态正常执行任务的,虽然在处理自定义信号的时候,进程当前就处于用户态,但是这样的状态和默认状态下回到用户态的逻辑是不同的。:首先明确一点,进程在运行的时候,就是单纯的在运行,无法估计其它事务,只有当涉及时间片的切换或出现异常情况,进程暂时没有在运行的时候才能有机会对信号进行处理。即当进程正常运行,行使功能的时候,都是处于用户态的,但当进程需要进行进程切换时上下文信息、临时数据的保存,恢复新切换上来的进程的上下文信息和临时变量时进程是处于内核态的。...

2022-08-31 10:22:54 349

原创 进程间通信方式

实现共享内存的整个过程就是按照操作系统的模式来进行的,除此之外,对于该块物理内存空间,其申请和释放也是由操作系统决定的,在建立共享内存时,先要申请空间,再建立映射关系,共享内存任务完成之后,也要先解除映射关系,再释放该物理内存空间。2,共享内存:对于使用共享内存进行通信的两个进程而言,二者都是通过进程结构体、虚拟地址空间、页表映射到物理内存的同一块空间中,而物理内存中的这块空间,就是所谓的在进程间通信时,两个进程都能看到的同一份资源。1,管道通信:管道通信本质上是通过拷贝的方式在进程间实现数据传输。...

2022-08-31 09:07:47 117

原创 虚拟内存和页表

由于每一个进程所拥有的虚拟内存结构都是相同的,所以,每一个进程都认为自己拥有全部的内存空间。本质上讲,一个进程在运行的时候,其所拥有的资源一定是保存在物理内存空间中的,但是当这个进程需要读取数据或资源时,却不是直接从物理内存中读取的,而是通过虚拟地址空间,借助页表,按照一定的映射规则,帮助进程按照虚拟地址空间中的地址找到物理内存中的地址。对于不同的进程而言,3G用户空间中的内容不同的进程是不同的,但是在1G内核空间中,由于均面向的操作系统,所以每一个进程1G内核空间中的内容都是相同的。...

2022-08-30 09:44:09 160

原创 【操作系统】进程、线程和协程相关问题

2,线程切换:线程的切换分为两种情况,当不同进程下的线程切换时,具体的过程和进程切换几乎一致,但同一进程下的不同线程切换时,由于同一进程下的不同线程是共享该进程的空间和资源的,所以此时,线程所需的开销就会小很多,需要进行处理的只有每一个线程所专有的寄存器和栈。对于进程的切换而言,当某一个进程在时间片内正常运行的时候,是处于用户态的,但是涉及到进程的切换时,由于需要上下文信息的保存,页表的切换等操作,此时被切换下去和切换上来的进程都是处于内核态的。线程是进程中的控制单元,负责当前进程中程序的执行。......

2022-08-29 10:56:15 284

原创 自主实现HTTP服务器项目逻辑

由于请求报文不一定有请求正文,所以要先对请求报头和请求行进行读取和分析,从中拿出必要的参数,如请求方法(GET/POST),统一资源定位符以及可能有的正文长度等相关信息。(3)是否需要调用CGI机制,如果带参,那参数一定是需要服务器端的可执行程序进行处理的,那就一定要调用CGI机制,无论是GET还是POST方法,都需要。TCP层的功能也就到此为止了。本项目是建立在TCP协议的基础上,实现HTTP层的功能,可以根据客户端的请求返回相应的资源,也可以调用客户端申请的可执行程序对其传递的参数进行处理。...

2022-08-27 09:58:00 1003

原创 OJ题目14--大数运算问题

在对数字的计算中,经常会有比较大的数字的运算,这些数字本身或者数字之间运算的结果有可能超出整型甚至长整型的处理范围,这种情况下,想要继续进行对这一类“大数”的运算,就需要改变思路,借助字符串的帮助,结合原始的,整型数字计算时的逻辑,对数字进行运算。这样做无形之间将很大数字的计算转变成某一位上极小数字的计算,每一位上计算完成之后在将其按照字符串的方式排列起来,而不是两个庞大数字之间大规模的计算。而最终返回的字符串如果将其转化成整型,其数值就等于最终应有的结果。1,415. 字符串相加 - 力扣(LeetC

2022-03-20 12:41:10 928 1

原创 OJ题目13--预测赢家问题

1,877. 石子游戏 - 力扣(LeetCode) (leetcode-cn.com)石子游戏可抽象成数组,即数组中有偶数个元素,且所有元素的和为奇数,两个玩家一次进行选择,只能选择当前数组中的第一个或最后一个元素。数组中元素的和为奇数,亦即一定能分出胜负。假设两个玩家都会做出最优解(这个假设是游戏类问题的关键),判断先手是否能获胜。事实上,先手一定能获胜,由于数组中共有偶数个元素,则首元素下标0为偶数,尾元素下标是偶数减一,为奇数,如果先手选择首元素,那后手只有两个选择,下标为1的元素或尾元素,

2022-03-15 20:26:49 3901

原创 OJ题目12--打家劫舍问题

打家劫舍问题本质上讲是动态规划问题。相比于普通的数组遍历,这类问题会有额外的限制条件,比如不能访问相邻的两个节点,抑或是第二题中普通的数组变成了环形数组。1,198. 打家劫舍 - 力扣(LeetCode) (leetcode-cn.com)题目要求不能偷盗相邻的两间屋子,求偷盗的最大收益。求解本题的思路是,如果想要偷盗一间屋子,那就不能偷盗前一间,也就是说偷盗完这间屋子的最大收益等于偷盗完这间屋子的前两间屋子的最大收益加上偷盗当前屋子的收益。当然还有另一种选择,那就是偷盗这间屋子的前一间,跳过当前

2022-03-14 22:08:06 306

原创 OJ题目11--移除数组中的特定元素

对于该类问题而言,与其说是移除数组中的特定元素,不如说是想办法留下数组中符合要求的元素。有了这一点认识之后,就会有如下的解题思路。创建另外一个数组,定义两个指针同时指向两个数组的开始位置。原始数组的指针向后遍历整个数组,并判断当前遍历到的元素是否符合要求,当原始数组的指针指向的元素符合要求时,将该值赋给新数组的指针指向的位置,然后两个指针同时向后移动一位。反之,原始数组的指针继续向后寻找,新数组的指针由于没有接收到合适的值,因此原地不动。经历完这一系列的操作之后,新的数组接收的全是符合要求的值,这样

2022-03-07 17:02:33 292

原创 OJ题目10--数字间的抑或,一场集体消消乐

抑或的定义是,只有当两个二进制数上的对应位相同时为0,相异时为1。这就让按位抑或具有了这样的功能,即让两个相同的数字抑或后的结果为0,如果是多个数字,只要这些数字两两相同,那么在集体抑或后,无论抑或过程中的顺序如何,都只会影响抑或的过程,但不会影响最终结果,即集体抑或的结果一定为0。1,面试题 17.04. 消失的数字 - 力扣(LeetCode) (leetcode-cn.com)本题当然可以采用将数字从1到n相加,再减去数组中的所有元素的做法,但这里介绍抑或方法。(抑或:均为1,则为0,其余情况

2022-03-06 17:21:26 477

原创 OJ题目9--最小路径、最小消耗的动态规划问题

一般来讲,涉及到最小路径的问题,目标都会有一个固定的行走模式,也就是说对于行走范围内的某一点而言,到达该点的各种可能性是确定了的(被确定了的行走模式所约束)。那么走到一点的最小消耗,就等于所有差一步就能到达该点的点中的最小消耗再加上该点本身的消耗。动态规划则实时的记录已经求出来的各个点的消耗的最小值,并将这些值作为后面计算的基础。1,​​​​​​剑指 Offer II 100. 三角形中最小路径之和 - 力扣(LeetCode) (leetcode-cn.com)​​​​​一个三角形矩阵,每一位上的

2022-03-05 20:32:04 688

原创 OJ题目8--动态规划问题

1,​​​​​​509. 斐波那契数 - 力扣(LeetCode) (leetcode-cn.com)过去一直用递归法,但由于栈区空间的限制,当递归过深时容易发生栈溢出。int fib(int n){ if(n==0) { return 0; } else if(n==1) { return 1; } else { return fib(n-1)+fib(n-2); }}

2022-03-03 19:26:15 185

原创 OJ题目7--数组元素的局部选择和抛弃问题

对于常规的求出数组中差值最大的两个元素及二者的差值时,对数组进行一次遍历,分别动态存储数组中当前的最大及最小值即可。但很多情况下,实际中的数据也可以抽象成一个数组,但是问题却要比简单的找出最大差值要复杂一些,因为根据实际情况,对问题的求解会有诸多限制条件。比如股票的买卖,买入股票的时间一定要早于卖出股票的时间。这时就不能把范围扩大到整个数组中,而是在当前数字的后面。1,121. 买卖股票的最佳时机 - 力扣(LeetCode) (leetcode-cn.com)本题的解题思路:我想要股票获得更大的利

2022-02-24 16:37:33 347

原创 OJ题目6--数字游戏问题

在OJ题目中经常会出现两个玩家分先后手玩数字游戏的问题,两个玩家会遵循相同的规则,题目还会特别注明,两个玩家在每一步上都会做最优解,事实上,看到这句话时,说明这道题一定是有规律可循的,而且规律往往相当简单(如果玩家不按套路出牌或者瞎玩的话,整个游戏过程也一定不可能用简单的程序模拟),当找到规律时,这一类问题也就被解决了。1,292. Nim 游戏 - 力扣(LeetCode) (leetcode-cn.com)这个游戏的规则是有一堆石子,我和另一个人玩,我先拿,另一个人后拿,每一次可以拿1,2,

2022-02-22 20:24:23 2949

原创 OJ题目5--一个数组中各数字出现的次数问题

对于一个数组,想要知道这个数组中每一个数字出现的次数,并将每一个数字出现的次数以数组的形式记录下来。以数组arr为例,可以创建一个新的、和arr数组等长的数组tmp(因为数组中的每一个数字都可能只出现一次),然后分别让tmp[arr[i]]++(这里arr[i]后面一般要减一,但没有必要,在解题过程中前后能对应即可),这时tmp数组中下标为k的那一位上记录的就是数字k出现的次数了。(很简单,不要想复杂了)1,448. 找到所有数组中消失的数字 - 力扣(LeetCode) (leetcode-cn.co

2022-02-20 19:37:40 504

原创 OJ题目4--计算二进制数中1的个数的几种方法

在有关二进制的题目中,计算二进制数中有几个1往往是解决问题的基础。1,剑指 Offer 15. 二进制中1的个数 - 力扣(LeetCode) (leetcode-cn.com)如果一个数除二会余1,则该数的二进制形式的最后一位会是1,否则是0。如果要计算下一位,则对该数除以二即可。int hammingWeight(uint32_t n) { int count=0; while(n>0) { if(n%2==1) {

2022-02-19 18:26:50 337

原创 OJ题目3--数组或二叉树中的元素组成二进制数的问题

对于按照数组或二叉树中的元素(在这类题目中一般是0和1)来组合成二进制数的问题,得到想要求的二进制数很简单,按照数组或者二叉树的规则遍历即可,但问题出在如何在依次读取元素的同时动态计算每读取一个元素后新生成的值。想要求解这个问题,就要先分析在依次向二进制数的末端插入新元素时,二进制数中原先的元素都发生了哪些变化。每当新插入一个元素时,原先的每一个元素都相应的提升一位,而对于二进制数而言,每提升一位,该位上的值变成原来的二倍(就类似十进制数变成原来的十倍,八进制数则是八倍),而新增加的一位就是该位上新增的

2022-02-17 22:20:05 323

原创 76天总结

离上一次总结已经过去21天了,好几次想着有时间总结一下,不是没有时间就是忍不住想多玩一会,一直拖到今天。回顾这21天的话,觉得进步比以前缓慢了,这也正常,毕竟学C++之前就定下了尽量拉平学习曲线的既定方针,这些天听课听得相当痛苦,但好在最后理解的都理解了。现在离开学还有10天,利用这10天好好把primer plus的书看一看,程序自己实现一下,就为了熟悉那些字符和适应C++的编程习惯。如果这10天能够高质量的完成的话,不需要全看完,我只需要看完前10章,再把比特课程中比较难理解的概念好好总结一下,我就算是

2022-02-11 00:06:49 308

原创 数据结构--归并排序(复习)

对于归并排序而言,最基本的类型是2-路归并,具体来说就是将待排序序列中前后两个相邻的有序序列归并为一个有序序列,注意,这里的两个序列都需要是有序的,两个无序的序列是无法归并的。但是很多时候待排序的数组中并没有现成的两个有序子数组供归并排序,这时候就需要人为制造局部有序的数组,在数组的每一个小区间都人为制造出有序数组,就可以从局部到整体,积少成多的将整个数组变为有序,这就是归并排序的思路。注:按照归并排序的思路,对于两个有序数组而言,如果直接将元素插入到它在排序后应该在的位置上,那势必会覆盖掉原来的元素,

2022-02-07 22:57:02 979

原创 数据结构--快速排序(复习)

快速排序的核心思想是,对于一个数组,当我选定其中的一个数值(这里以数组当前的首元素为例),我通过交换等手段让数组中所有比该元素小的元素都跑到该元素的左边,所有比该元素大的元素都跑到该元素右边。完成后,再分别对该元素的左右两部分子数组进行同样的操作,依此类推,若干次运算之后,整个数组就可以排好序了。对于快速排序而言,每次确定中心点并以此为依据交换元素时,对于整个数组而言(因为计算几次之后,整个数组会被分成若干个小数组),时间复杂度都为O(N),因此制约快速排序速度的因素就是排序时处理的次数,亦即多少次循环

2022-02-06 22:15:10 477

原创 数据结构--选择排序和冒泡排序(复习)

对于选择排序和冒泡排序而言,二者的相同点是每一次循环结束后,都有元素被放到了最终其应该在的位置上。不同点在于冒泡排序每一次循环中会改变许多元素的先后顺序,一环套一环,而选择排序则是直接在众多待排序元素中直接找到当前的最大/最小值,并直接将其放到应该在的位置上。对于选择排序而言,可以对其进行加速,即每一次循环,不但要找最小值,同时也要找最大值,遍历了一遍未被排序的部分确定了最大最小值之后,将最大最小值分别放到当前的第一和倒数第一的位置上。这样可以把效率提升二倍。但是也会出现问题,由于最小值要和第一个数相交

2022-02-04 19:36:28 609

原创 数据结构--插入排序及衍生出的希尔排序(复习)

1,插入排序:插入排序之所以叫插入排序,是根据其排序特点来命名的。在插入排序的过程中,在整个待排序的数组内,具有从小到大顺序的元素个数从前向后逐次增加。每一次新的排序开始前,紧跟在已经排好序的小数组后面的第一个元素就会从后向前分别和小数组中的元素比较,如果该元素比数组中的一个元素小,那该元素的最终位置就应该在比它大的那个元素之前,继续向前比较,直到遇到第一个比它小的元素为止。只要该元素比某一个元素大,那这个元素就比前面的元素都要大,因为这个小数组之前就是排好序的了。最终这个元素所在的位置就是第一个比它小的元

2022-02-03 23:30:10 1070

原创 C++--this指针

在研究this指针之前首先要明确两个概念:1,面向过程编程和面向对象编程:就好比洗衣服,面向过程编程就是将洗衣服的每一个步骤都描述出来,而面向对象编程则是分别描述人要做哪些工作,洗衣机需要做哪些工作。C语言属于面向过程编程,C++属于面向对象编程,这也是这两种语言的根本区别之一。而面向对象编程也使得C++语言能够更好的应对规模更大,更复杂的项目。2,类和对象:C++中的类对应C语言中的结构体,如果在C++环境中使用C中的结构体,则结构体自动升级成类。类和结构体的主要不同是结构体只能定义变量,而类中还

2022-02-03 00:07:45 559

原创 OJ题目2--嵌套形式的递归

所谓嵌套形式的递归,按照我的理解就是递归的形式比较复杂,不是简单的一句话能说清楚的,这是就需要两层递归进行嵌套,以达到目的。比如计算一个二叉树中有几个节点的问题,求解这个问题的根本逻辑就是一个二叉树的节点个数等于根节点本身加上根节点的左子树中的节点树和根节点右子树中的节点数。依此类推,直到计算到根节点处为止(判断的标准是计算完以叶子节点作为根节点的那次递归之后,其左右孩子节点必然为空,因此节点为空也就成为了结束条件)。上述这个问题的简单逻辑当然可以通过一次递归来实现。但是许多递归问题的逻辑并非总是这么简单,

2022-02-01 21:01:49 1248

原创 数据结构--堆的实现(复习)

特别需要注意的是堆是用数组实现的,因为堆中的元素是顺序存储的,而数组中的元素也是顺序存储的。(一般的二叉树不用数组来实现,而是用链表来实现,因为普通的二叉树中可能存储元素的密度很低,用连续存储的结构会造成大量的空间浪费。堆结构的初始化:和初始化一个数组类似,都是创建一个指针,和一些以后能用到的值。(针对结构体而言,不同于链表中结构体就代表链表中的某一个具体的节点,有关数组的结构体相当于对数组整体都可以施加影响的操作)void HeapInit(HP* hp){ assert(hp); hp-

2022-01-29 20:57:06 968 1

原创 OJ题目--1,创建数组储存字符串中出现的字符次数问题(5)

1,求字符串中第一个只出现一次的字符:第一个只出现一次的字符_牛客题霸_牛客网 (nowcoder.com)由于字符在计算机中归根结底是由阿斯克码所代表的,因此可以创建一个数组,每一个字符出现的次数就放在数组中其阿斯克码所对应的下标位置,到时候,从第一个字符对应的阿斯克码的下标开始寻找,找到的第一个元素为1的字符即为想要找的字符。注:这里第二个for循环中,在创建的table数组中,是按照字符出现的顺序在数组中寻找字符出现的顺序的。获得数组中存储的每一个字符出现次数,还可以从1到128依次遍历,但是

2022-01-28 20:54:55 527

原创 数据结构--双向链表的实现(复习)

相比于之前的顺序表和单链表,双向链表的实现更复杂,但是到了实操环节则更简单。就好比高速公路相比一般的柏油马路更难修建,但是汽车在高速公路上却可以跑得更快。需要特别注意的是,双向带头链表为空的条件是head->next=next。head节点处不存储数据,head节点充当哨兵位节点。当双向链表中只有一个哨兵位节点时,说明双向链表为空。结构体的定义:双向链表有两个指针,和一个数值。定义结构体时考虑这三个部分即可。typedef int LTDateType;typedef struct L

2022-01-27 22:52:33 1255

原创 数据结构--链表的实现(复习)

单链表的定义不同于顺序表,顺序表是整体定义的,需要定义顺序表的容量和当前包含多少元素。而链表只需要定义单个元素的种类和指向下一个元素的指针即可。(相比之下,同样是借助结构体,顺序表的结构体是整个链表,而链表的结构体只能代表其中的一个节点。typedef int SLTDatatype;typedef struct SLTNode{ SLTDatatype data; SLTNode* next;}SLTNode;打印出链表中的每一个元素:void SListPrint(SLTNode*

2022-01-26 21:35:13 851

原创 数据结构--顺序表的实现(复习)

检查为顺序表所准备的存储空间是否够用的函数:如果存放在顺序表中的元素个数已经等于了顺序表的容量,那就需要为顺序表新增存储空间,如果原空间原本就为空,则为其新申请的空间为4字节,否则新申请的空间大小为原空间的二倍。void SeqListCheckCapacity(SL* ps){ if (ps->capacity == ps->size) { SLDataType newcapacity = ps->capacity == 0 ? 4 : (ps->capacity)

2022-01-25 22:20:25 160

原创 55天总结

从2021年11月27号开始决定开始转码开始,到今天,1月20号,正好55天。在这55天里,完成了C语言的学习(虽然很基础),还有数据结构的学习。从1月22号到2月13号开学,刨去各种聚会,过年,休息之外,还有大概20天的时间。这二十天的时间里,要按部就班的把之前学过的数据结构复习完,每天早上照旧进行C++的学习,C++在开学前有应该能上10节课左右,每天听一部分,尽量慢,千万不要着急,之前为自己争取的宝贵时间可以让目前C++的学习曲线尽量拉平。对于C++这一门语言来说,各种东西加到一起,我给自己100

2022-01-20 22:38:27 268

原创 数据结构-直接排序

1,hoare版本hoare版本分为两种情况,第一种是定义两个整型L和R,分别对应待排序数组第一和最后一个元素的下标。同时,定义一整型k对应第一个元素的下标。两种情况分别为:一,当选择最右边的值做key时,右边(R)先走,左边(L)后走,L找比key大的数,R找比key小的数,当二者均找到目标元素时,将两元素对调,然后继续L先走,Y后走。当L与Y相遇时,将相遇的位置处的节点与最左边key对应的节点互换。二,当选择最左边的值做key时,左边(L)先走,右边(R)后走,L找比key大的数,R找比

2022-01-19 19:57:21 528

原创 数据结构-排序

1,直接插入排序:比如说对于一个有n个数字的数组,我要将其按从小到大的顺序排序,我先假定现在排在第一位的元素就是第一个,然后将第二个元素与其相比较,如果第二个元素较小,则先令int x=a[2],a[2]=a[1](将第一个元素的值赋给第二个位置)再令a[1]=x(这一过程类似交换两个变量的值的操作,都需要额外定义一个变量以避免在交换的过程中变量的值互相覆盖)依此类推,在比较k次时,前k+1个元素的值都已经是有序的了,因此后面的值再参与比较时,只需要从后向前依次比较,知道遇到某元素<k时,brea

2022-01-18 22:45:36 396

原创 二叉树中的递归思想

按我的理解,递归的过程就是一个上楼梯加上下楼梯的过程(每一层台阶都是相同的,但是一级比一级高),在设计递归程序时,除了“台阶”之外,还要设计一个边界条件,在到达这个边界条件时,递归程序内部不会再向下递归(套娃),而是直接返回一个返回值,这个返回值又会成为其上一层递归的初始条件,这样就相当于开始一级一级的下楼梯。1,前、中、后序遍历以前序遍历为例,先访问根节点,然后是左节点,然后是右节点,并依此类推,访问全部的节点。由于在整个访问过程中的每一步,都遵循着上述的逻辑,因此这里就非常适合用递归思想来解决。

2022-01-17 21:54:49 2129 1

原创 数据结构-堆的插入和排序(向上调整+向下调整)

堆在本质上就是一个用数组实现的二叉树,而堆在排序方面又分为大堆和小堆,在大堆中,任何一个双亲结点都大于其孩子结点,小堆反之。向上调整:堆排序本身并不难,但问题在于向堆中插入一个节点时,由于该节点可能拥有任何值,因此该节点插入后,该堆可能就不符合原先大堆的特点了。这时就需要向上调整。对于新插入的孩子节点而言,假设其下标为child(child的值等于当前数组的长度-1),如何找到其双亲节点呢?孩子节点和双亲节点的下标具有如下关系:parent=(child-1)/2。根据这一关系,就可以找到新插入

2022-01-16 21:26:21 1115

原创 数据结构-用栈实现队列

用栈实现队列本质上是用两个后进先出的栈来实现后进后出的效果。思路:初始化两个栈,一个栈中有数据,一个为空。将非空的栈中的数据依次取出来,放到空栈中,全部元素都处理完之后,在按栈的顺序把原本的空栈中的数据依次取出来。由于栈先进后出的特点,先进入非空栈的元素也就会后出栈,也就会后进入空栈中,也就会先从空栈中出栈。这样就实现了队列先进先出的性质。代码实现:typedef struct{ ST pushST; ST popST;}MyQueue;MyQueue* myQueueCre..

2022-01-15 21:47:23 205 1

原创 数据结构-用队列实现栈

用队列实现栈在本质上就是实现栈“后进先出”的特点。思路:用两个队列来实现,一个队列中存储所有的元素,另一个队列为空。为了实现后进先出的目的,我需要考虑如何把最后一个进入队列的元素(即非空队列中的最后一个元素)最先拿出来。具体实现方式是:先把非空队列中除最后一个元素之外的所有元素按顺序拿出来放到空队列中,拿出来之后立刻将其在原队列中删除。然后返回原先的非空队列中的最后一个值(很容易做到,这时该节点已成为该队列中的第一个元素)。代码实现:typedef struct { Queue .

2022-01-15 20:17:05 241

空空如也

空空如也

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

TA关注的人

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