自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 【Linux】多线程:线程控制

在学习完pthread_create函数之后,我们了解到该函数有一个形参为函数指针,也就是我们常说的“回调函数”,当线程创建完毕之后,该线程会立刻去执行该函数。在分支线程中,执行流程主要是:1、将需要执行的任务的函数指针通过参数传递给pthread_create函数,当线程创建完毕后,该线程就会跳转到该函数的起始地址处执行该函数的代码。当然,线程分离除了由主线程对其他线程进行分离外,还可以由线程本身进行分离,这时需要用到pthread_self函数获取该线程自身的线程ID。1、 从线程函数 return。

2024-09-06 14:42:13 887

原创 【Linux】多线程:POSIX库、线程管理、线程ID

我们知道,不同的操作系统中,实现线程的方式并不一致,这就造成了在Linux系统中使用系统调用编写的多线程程序在其他操作系统中可能并不适用。这是因为Linux中的线程是用户级线程,由POSIX库对其进行管理,所以我们在程序中所打印出来的线程ID实际是库给我们所分配的线程唯一标识。:在内核态中,线程ID和进程ID的管理是由内核直接处理的。我们能够观察到,这两个线程同属于一个进程之中,并且有一个线程(轻量级进程)的ID与进程的ID相同,这就是我们所说的“主线程”,主线程并不需要我们手动创建,

2024-09-05 18:47:12 870

原创 【Linux】多线程:线程概念,线程与进程的区别与联系,多线程相较于多进程的优势

举个更通俗的例子:在我们国家中,家庭通常是政府进行资源分配的单位,则家庭可以视为进程,而一个家庭至少包含一个家庭成员,也可包含多个,且家庭成员共享家庭的资源,但家庭成员又有各自的隐私,因此可以将家庭成员视为线程。所以我们在Linux系统中编写程序时,我们所面对的是pthread库为我们提供的管理“线程”的方法,在内核中实际上是被当作轻量级进程(LWP)来处理的,因此我们称Linux中的线程为“用户级线程”。因此,在使用多线程时,由于多线程共享所属进程中的资源,因此减少了资源的频繁切换。

2024-09-04 23:40:15 604

原创 【Linux】网络编程套接字Scoket:UDP网络编程

套接字是操作系统内核中的一个数据结构,它是网络中的节点进行相互通信的门户,是网络进程的ID。网络通信归根到底还是进程间的通信(不同计算机上的进程间通信)。在网络中,每一个节点(计算机或路由)都有一个网络地址,也就是IP地址。在两个进程进行通信时,首先要确定各自所在的网络节点的网络地址。但是,网络地址只能确定进程所在的计算机,而一台计算机上很可能同时运行着多个进程,所以仅凭网络地址还不能确定到底要和网络中的哪一个进程进行通信,因此套接字中还需要包括其他的信息,也就是端口号(PORT)。

2024-08-09 18:24:14 819

原创 【Linux】进程间通信(3):共享内存

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间,进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种互斥与同步的机制,互斥锁和信号量都可以。

2024-07-31 18:24:56 833

原创 【Linux】进程间通信(2):命名管道

命名管道(FIFO,First In First Out)是一种特殊的文件类型,用于在不同进程之间进行数据交换。它的设计允许一个进程将数据写入管道,而另一个进程从管道中读取数据。这种机制使得不同进程能够通过管道进行通信,而不需要直接共享内存或使用其他复杂的同步机制。

2024-07-29 20:02:08 600

原创 【Linux】模拟实现简易shell命令行:基于进程创建、进程等待、进程替换等知识的练习

程序功能:模拟实现一个自己的shell执行命令行。涉及知识:字符串输入及操作函数、子进程创建、进程等待、进程替换、环境变量及获取、添加环境变量的函数额外需要了解的功能函数:chdir(char* path)函数——改变当前工作路径名词解释:内建命令(Built-in Commands)是指在命令行解释器(如 Bash、Zsh 等)中直接实现的命令。这些命令不需要调用外部程序或二进制文件,而是由解释器本身提供和处理。注意事项:易错点 :int putenv(char *str);

2024-07-28 18:01:07 224

原创 【Linux】基于匿名管道通信实现的简易进程池

进程池是一种技术应用,它由资源进程和管理进程组成。资源进程是预先创建好的空闲进程,用于处理分配给它们的任务。管理进程则负责创建资源进程、分配任务给空闲的资源进程,并在任务完成后回收这些资源进程。

2024-07-28 17:49:40 652

原创 【Linux】进程间通信(1):进程通信概念与匿名管道

进程间通信、管道、匿名管道

2024-07-27 19:51:24 751

原创 自我反思与暑假及大三上学期规划

在这个暑假中,我会继续用在CSDN上发布文章的方式来对我学习的知识进行巩固,其中涉及到C++,数据结构与算法,Linux操作系统。在学校开设的课程上,进行QT与51单片机的学习与入门,并在寒假之前彻底完成对QT和GIT的学习,尝试做一个QT方向的项目。但是开学以后,我并没有把重心放在期望自己应该做的事情上,更多的时间花费在了处理学院的相关事务。现在看来,大二学年在专业课的学习上更多的是“碌碌无为”,对于数据结构与算法和C++的学习也是有许多不足,以至于目前为止我仍然觉得自己没有什么能拿得出手的“长处”。

2024-07-02 22:26:14 492 3

原创 最大子矩阵:前缀和 + 线性动态规划

那么它的子矩阵就是矩阵中的某一片矩阵型的区域,那所要求的“最大子矩阵”的自然是找到在所有子矩阵中,矩阵元素和最大的那个矩阵。第二种情况是将当前位置的元素加入到之前的子序列中,即从当前位置开始新的子序列。dp[i - 1] + nums[i - 1] 表示从当前位置向前延伸的子序列的和,即以 nums[i - 1] 结尾的子序列和加上当前位置的元素值。其实通过上面的例子,我们不难发现进行预处理后的前缀和数组,仍然可以表示原数组的元素,更方便的是对于求原数组圈定矩阵元素和,在处理后的数组中仅通过使用。

2024-05-13 02:39:51 710 1

原创 【Linux】进程管理(2):进程控制

事实上,只有execve才是真正的系统调用,其它五个函数最终都是调用的execve,所以execve在man手册的第2节,而其它五个函数在man手册的第3节,也就是说其他五个函数实际上是对系统调用execve进行了封装,以满足不同用户的不同调用场景的。在这种情况下,操作系统通常会将孤儿进程的父进程设置为 init 进程(进程号为 1),并由 init 进程接管孤儿进程的管理。孤儿进程的退出方式与其他进程相同。函数会返回两次,一次是在父进程的上下文中返回子进程的 PID,另一次是在子进程的上下文中返回 0。

2024-04-02 22:33:43 1100

原创 【Linux】进程管理(1):进程及概念精讲

进程概念引入二、进程的描述与组织:进程控制块(PCB)与进程标识符(PID)三、fork函数:创建子进程四、进程的地址空间:虚拟内存与写时复制五、进程查看六、进程状态七、父子进程、孤儿进程、僵尸进程孤儿进程:僵尸进程八、进程的优先级九、环境变量【选学】 十、Linux操作系统进程的调度1、活动队列详解2、过期队列详解3、O(1)调度算法

2024-03-31 20:26:05 1072 1

原创 深入了解 C++ 中的 string 类型

是 C++ 标准库中的一个类,用于表示字符串。动态大小允许在运行时动态调整字符串的长度,不需要在编译时指定固定大小。自动管理内存类会自动管理字符串的内存分配和释放,无需手动管理内存。可变性中的字符串内容是可以被修改的,可以通过各种操作来修改字符串的内容。

2024-03-17 01:24:07 479

原创 排序算法大全:冒泡排序【含优化】,选择排序【含优化】,直接插入排序,希尔排序,堆排序,快速排序【含3种实现版本及非递归实现】,归并排序【含非递归实现】。详细图解,文字解释,代码实现,性能分析。

七大排序详细图解,优化,代码实现。一、冒泡排序1、冒泡排序思想2、冒泡排序算法的性能分析二、选择排序1、选择排序思想2、选择排序算法的性能分析三、直接插入排序1、直接插入排序思想2、直接插入排序算法的性能分析四、希尔排序1、希尔排序思想2、希尔排序算法的性能分析五、堆排序六、快速排序1、hoare划分法2、挖坑法3、前后指针法快速排序优化快速排序的非递归实现七、归并排序1、归并排序递归实现2、归并排序非递归实现

2024-02-09 18:19:42 1077 1

原创 【C++】初识模板:函数模板和类模板

class 类模板名// 类内成员定义。

2024-02-09 18:03:56 762

原创 【C++】内存管理

一、C/C++ 内存分布二、C++动态管理内存:new与delete详解1、new与delete的实现原理:2、new与delete的使用三、malloc/free和new/delete的区别

2024-02-08 23:54:16 1061 2

原创 【C++】友元:友元函数与友元类

友元(friend)是C++中的一种特殊关系,用于在类之间共享访问权限。通过将一个函数或类声明为另一个类的友元,我们可以允许友元访问声明类的非公有成员。问题:现在尝试去重载operator<<,然后发现没办法将operator<<重载成成员函数。输出流对象和隐含的this指针在抢占第一个参数的位置。友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在。但又会导致类外没办法访问成员,此时就需要友元来解决。类的内部声明,声明时需要加friend关键字。

2024-02-07 22:49:46 342

原创 【C++】静态成员变量和静态成员函数

定义时不添加static关键字,类中只是声明3.类静态成员即可用。

2024-02-06 21:16:49 455

原创 【C++】构造函数、初始化列表,析构函数,拷贝构造函数,运算符重载

一、构造函数构造函数的形式及其使用:初始化列表:explicit关键字二、析构函数1 .概念2.特性析构函数的调用顺序三、拷贝构造函数特性:四、运算符重载(部分)1、概念2、赋值运算符重载3、前置++和后置++的实现

2024-02-06 21:02:57 768

原创 【数据结构与算法】二叉树前序,中序,后序遍历非递归版。Leetcode接口

指针为空,则表示已经到达最左边的叶子节点,此时将栈顶节点出栈,将节点的值存入数组。指向该节点的右子树。

2024-02-01 21:50:32 594

原创 【C++】this指针详解

通过在 “this” 指针前面加上作用域限定符,我们可以明确指定要访问的是基类中的成员。与普通指针不同,“this” 指针是一个常量指针,指向的对象是不可变的。通过使用 “this” 指针,我们可以将当前对象传递给其他函数以供使用。当成员变量与函数参数名字相同时,使用 “this->” 可以明确指定要访问的是成员变量而非函数参数。在成员函数中,可以使用 “this” 指针来访问当前对象的成员变量。函数使用了 “this” 指针来打印输出当前对象的成员变量。函数,通过使用指针来访问当前对象的成员函数。

2024-02-01 12:27:03 322

原创 【C++】缺省函数

它还能够提供一个合适的默认行为,当不提供特定参数值时,函数可以以某种约定的方式运行。请注意,在函数声明或者函数定义的使用中,缺省参数只需在函数原型或者定义的其中之一中提供即可。而且,一旦某个函数的声明或者定义中提供了默认值,那么其他使用的声明或定义必须保持一致。在 C++ 中,缺省函数(Default Function)是指在函数声明中为函数的参数提供默认值的函数。当调用这个函数时,如果没有提供相应参数的值,那么将使用该参数的默认值。函数中,我们可以选择传递任意数量的参数,缺省的参数将使用其默认值。

2024-01-22 12:12:16 435

原创 【C++】函数重载

函数重载是 C++ 中一个灵活强大的特性,允许我们使用相同的函数名来处理不同的参数类型和数量。通过函数重载,我们可以提高代码的可读性和可维护性,并避免命名冲突。需要注意的是,在函数重载使用中,应避免产生二义性错误,以确保编译器能够正确匹配函数。

2024-01-22 12:10:33 431

原创 【C++】命名空间namespace详解

使用namespace关键字可以定义命名空间。可以在命名空间中包含变量、函数、类、结构体等。// 变量、函数、类等的声明和定义命名空间是 C++ 中组织代码的一种方式,可以将相关的实体置于同一个命名空间下,避免命名冲突。可以通过作用域解析运算符或using关键字来访问命名空间中的实体。嵌套命名空间可以在一个命名空间中定义另一个命名空间。使用命名空间可以提高代码的可读性和可维护性。

2024-01-22 12:00:37 533

原创 【数据结构与算法】归并排序详解:归并排序算法,归并排序非递归实现

在合并的过程中,如果遇到两个相等的元素,我们会先将来自前一个子数组的元素放入辅助数组,这样可以确保相等元素的相对顺序不会改变。合并时,使用双指针i和j分别指向两个子数组的起始位置,比较两个子数组对应位置上的元素大小,较小的元素放入temp数组中,同时移动指针,直到一个子数组遍历完成。通过不断调整gap的大小,将待排序数组进行分组和合并操作,直到得到一个完全有序的数组。在每一轮合并中,将数组分为多个大小为gap的子数组,将相邻的两个子数组合并为一个有序子数组。更新gap的值为2倍,继续下一轮合并。

2024-01-21 15:55:34 774

原创 【数据结构与算法】排序算法:直接插入排序,希尔排序详解

当比较相等元素时,由于只有当前元素小于等于已排序部分的某个元素时才插入,因此相等元素的相对次序不会发生改变。直接插入排序是一种简单直观的排序算法,其思想是通过构建已排序部分和未排序部分,将待排序元素按照大小逐个插入到已排序部分的正确位置中,完成排序。需要注意的是,尽管直接插入排序在最坏情况下的时间复杂度较高,但对于小规模或基本有序的序列,直接插入排序的性能较为优秀。希尔排序的思想是利用了插入排序对基本有序的序列性能较好的特点,通过提前部分排序减少了逆序对的数量,从而提高了排序效率。

2024-01-19 14:59:37 374

原创 【数据结构与算法】quicksort快速排序算法大全:快速排序hoare法,快速排序挖坑法,快速排序前后指针法,快速排序优化,快速排序的非递归实现

每次处理子数组时,选择一个枢轴元素进行划分,并将划分点的下标入栈。然后根据划分点将子数组分成两部分,分别将左侧和右侧的子数组边界入栈。这样可以确保先处理左侧子数组,再处理右侧子数组,达到快速排序的效果。挖坑法是一种简洁的快速排序实现方式,它通过交替移动两个指针,将元素一个个填入坑位的方式来进行划分。根据划分点的下标更新子数组边界,将左侧子数组的开始位置和结束位置入栈,再将右侧子数组的开始位置和结束位置入栈。快速排序的非递归实现使用了栈来模拟递归的过程,这样可以避免使用系统栈导致的递归调用过深的问题。

2024-01-19 14:59:01 534

原创 【数据结构与算法】排序算法:冒泡排序,冒泡排序优化,选择排序、选择排序优化

冒泡排序的基本思想是通过相邻元素之间的比较和交换来逐步将最大(或最小)的元素移到右边(或左边)。思想:在优化版本的冒泡排序算法中,通过添加一个标记变量flag,可以在一轮排序过程中标记是否有进行过交换操作,通过这种方式,可以减少交换的次数,从而提高排序的效率。综上所述,选择排序的时间复杂度为O(n^2),空间复杂度为O(1),并且是一种不稳定的排序算法。通过每次从剩余未排序部分选择最小的元素,并将其放在已排序部分的末尾,逐步构建有序序列。优化版本的思想是在选择排序的基础上,

2024-01-18 18:28:46 617

原创 【数据结构】堆:堆的构建,堆的向上调整算法,堆的向下调整算法、堆排序

堆可以被看作是一棵完全二叉树的数组对象。即在存储结构上是数组,在逻辑结构上是一棵完全二叉树。在堆中,树的每个节点都满足堆属性,即父节点的值大于(或小于)其子节点的值。具体而言,对于最大堆,父节点的值大于等于其子节点的值;而对于最小堆,则是父节点的值小于等于其子节点的值。这使得堆的根节点(常常是数组的第一个元素)成为堆中最大(或最小)的元素。

2024-01-18 17:48:03 1572

原创 【数据结构】二叉树的创建和遍历:前序遍历,中序遍历,后序遍历,层次遍历

二叉树(Binary Tree)是有n(n≥0)个结点的有限集合:(1) 该集合或者为空(n=0);(2)或者由一个根结点及两个不相交的分别称为左子树和右子树组成的非空树;(3)左子树和右子树同样又都是二叉树。在一棵非空的二叉树中,每个结点至多只有两棵子树,分别称为左子树和右子树,且左右子树的次序不能任意交换。所以,二叉树是特殊的有序树。值得注意的是,由于二叉树上任结点的子树有左、右之分,因此即使一个结点只有一棵非空子树,仍须区别它是该结点的左子树还是右子树,这是与树不同的。

2024-01-03 15:21:41 1805

原创 【数据结构】二叉树的基本操作大全,学会二叉树基本操作这一篇就够了:二叉树前序、中序、后序、层次遍历;求二叉树总结点个数,叶子结点个数,二叉树第k层的结点个数;求二叉树的高度;在二叉树中查找值为x的结点

【数据结构】二叉树的基本操作大全,学会二叉树基本操作这一篇就够了:二叉树前序、中序、后序、层次遍历;求二叉树总结点个数,叶子结点个数,二叉树第k层的结点个数;求二叉树的高度;在二叉树中查找值为x的结点

2024-01-03 03:09:29 2204

原创 【数据结构】循环队列(数组实现)

将顺序存储队列的元素的一维数组首尾相接,形成一个环状,如下图所示,这种形式表示的队列称为循环队列。循环队列仍然是顺序队列结构,只是逻辑上和前面的顺序队列有所不同。#define MAXLEN 6 // 定义环形队列的最大长度为 6// 定义数据类型为整型typedef struct CircularQueue // 定义环形队列的结构体// 定义存储数据的数组// 定义队头和队尾指针int size;// 定义队列元素个数} CQueue;

2023-12-29 12:45:22 1644

原创 【数据结构】数组实现队列(详细版)

队列是一种基本的数据结构,它是一种先进先出(First In First Out,FIFO)的线性结构。队列只允许在表的一端进行插入,而在另一端进行删除操作。这就相当于把数据排成一排,先插入的排在前面,后插入的排在后面,之后进行删除操作时也只能从前面依次删除。这种数据结构一般用于需要按照先后顺序进行处理的问题,如模拟系统、计算机网络中的缓存、操作系统中的进程调度等。队列的基本操作包括入队(插入元素到队尾)和出队(从队头删除元素)

2023-12-28 18:29:16 2447

原创 【数据结构】单链表实现队列

队列是一种常见的数据结构,它遵循先进先出(First-In-First-Out,FIFO)的原则。在队列中,新元素被添加到队尾,而只有队首的元素可以被移除。

2023-12-25 23:09:07 527

原创 【数据结构】单链表的基本操作(C语言版)

单链表(Singly linked list)是一种常见的数据结构,它由一个结点(Node)的链表构成,每个结点包含两个域:数据域和指针域。数据域用于存储结点的数据,指针域用于存储下一个结点的地址。单链表中的第一个结点被称为头结点(Head),它用来存放链表的基地址。头结点中的指针域指向链表的第一个结点,最后一个结点的指针域指向空地址,表示链表结束。// 数据域,存储结点的数据// 指针域,指向下一个结点}ListNode;

2023-12-25 22:19:10 1239

原创 Linux基础指令,vim,gcc,gdb,git,makefile基础操作

编译(Compiling):在编译阶段,预处理后的源代码将被转换为汇编语言。汇编(Assembling):在汇编阶段,汇编器接受编译器生成的汇编代码文件,并将其转换为机器可执行的二进制目标文件。预处理(Preprocessing):在这个阶段,gcc 会根据源代码中的预处理指令对代码进行预处理。需要注意的是,该命令会直接删除文件或目录,并且在删除之前没有任何提示信息,请谨慎使用。它允许你按页浏览文本文件,适用于较长的文件内容。命令还可以用于将多个文件的内容合并,并输出到一个文件或标准输出。

2023-11-11 18:00:00 249 1

原创 C语言中的宏定义

宏定义是一种预处理指令,用来在编译之前对代码进行替换处理。通过#define指令,我们可以为特定的标识符定义一个代表值或代码片段的宏。一旦定义了宏,编译器将会在编译过程中自动将它替换为相应的值或代码。#define 宏名 替换文本最简单的宏定义用法是将特定的标识符替换为一个常量。在程序中使用宏定义时,编译器会将所有的PI替换为3.14159。宏定义虽然功能强大,但如果不慎用可能会导致代码可读性下降或出现隐藏的错误。因此,在使用宏定义时应谨慎考虑,并确保遵循良好的编码规范。

2023-10-22 20:01:11 174 1

原创 【C语言】文件操作函数

函数在C语言中用于打开文件,并返回一个指向文件的指针,可以根据指定的文件名和打开模式进行不同类型的文件操作。函数关闭文件,以确保文件资源得到正确释放。函数用于打开一个具有指定文件名的文件,并返回一个文件指针,以供后续的文件读写操作使用。函数之后,应该确保不再需要对该文件进行操作,以免出现意外的错误。函数在关闭文件后,将无法再对该文件进行读写操作。函数用于关闭一个打开的文件,并释放与文件相关的资源。函数关闭文件,以确保文件资源被正确释放。需要注意的是,在操作文件之后,应该使用。在处理完文件后,应该调用。

2023-10-14 21:01:30 3997 1

原创 动态内存函数(malloc,free,calloc,realloc)

【代码】动态内存函数(malloc,free,calloc,realloc)

2023-10-01 21:12:50 110

空空如也

空空如也

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

TA关注的人

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