
C语言
文章平均质量分 79
从0开始讲解C语言
zhangcoder
大一 KEEP CODING!
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
126.【C语言】数据结构之归并排序非递归解法
介绍归并排序的非递归实现方法。首先回顾了递归解法,然后重点讲解了循环实现非递归归并排序的两种方案。针对数组元素个数为2的次方倍的情况,详细分析了gap控制分组归并的机制,给出了完整的代码框架。对于元素个数非2次方倍的情况,提出了两种处理边界越界的方法:一是归并完成后统一拷贝,二是边归并边拷贝。通过调试信息展示了分组归并的过程,并通过LeetCode测试验证了算法的正确性。最终推荐使用边归并边拷贝的方法,因其处理边界条件更简单高效。原创 2025-07-07 11:03:57 · 588 阅读 · 0 评论 -
125.【C语言】数据结构之归并排序递归解法
绍了归并排序递归算法的实现过程。首先通过重新排列数组的题目引出分治思想,然后详细讲解了归并排序的分治策略:将数组不断二分直到单个元素视为有序,再通过合并有序子序列完成排序。文章提供了完整的递归实现代码,包括临时数组的使用、区间划分和归并操作,并分析了时间复杂度为O(NlogN)。最后指出该算法对奇数个元素同样适用,并通过LeetCode测试验证了正确性,为后续讲解非递归实现做铺垫。原创 2025-07-06 19:19:28 · 1356 阅读 · 0 评论 -
130.【C语言】数据结构之基数排序(了解即可,实际应用较少)
基数排序是一种非比较类排序算法,通过分配和回收的方式对数字的每一位进行排序。首先解释了基数排序的基本原理,包括最低位优先法和最高位优先法,并通过一个具体的例子展示了基数排序的过程。接着分析了基数排序的时间复杂度,并给出了C++实现代码。最后提出了一个思考题:如何对包含负数的数组进行基数排序,并给出了相应的解决方案原创 2025-07-05 20:59:20 · 696 阅读 · 0 评论 -
E47.【C语言】零散的练习题(1)
char acX[] = "abc"等价为'a','b','c','\0'(字符串结尾隐藏\0) ,而char acY[] = { 'a','b','c' };由单个字符排列,结尾没有\0,因此acX占用的内存空间比acY占用的大,C正确,不选,且acX和acY没有用const修饰,因此A正确,不选。strlen求有效字符串的长度,而str_arg指向的字符串为"Hello"加上隐藏的\0一共5个字符,因此第二个打印4。,因此在定义指针时,不能修改指针所指向的内容,需要用const修饰。原创 2025-04-24 08:27:44 · 929 阅读 · 0 评论 -
【C语言】经验漫谈:应用情景下的移位操作巧分析
本文讲解枚举法和特值法,例子来自某修改器的逆向出的代码和MD5算法的源文件原创 2025-02-21 14:22:54 · 453 阅读 · 0 评论 -
128.【C语言】补充:循环结束后循环变量的值(反汇编分析)
0.准备工作1.反汇编下列C代码2.反汇编后分析先了解下jge指令格式逐指令分析3.结论4.拓展问题原创 2025-01-15 18:30:15 · 556 阅读 · 0 评论 -
127.【C语言】补充:函数的三种调用约定
先引入两个名词:调用者和被调用者,例如本代码的main函数为调用者,其调用add函数,则add函数为被调用者。区别在:清理栈(防止栈溢出)的方式不同,其中add esp,8和ret 8均为清理栈的指令,其中_add(int a,int b)后观察修改前后的反汇编代码是否有区别?add(int a,int b)后观察修改前后的反汇编代码是否有区别?答:显然当参数过多,寄存器不够用时,会用栈来辅助传参,而且一般情况下,最左边的两个参数(add(1,2,3,4)的1和2)清栈(即两者清栈的执行对象不同)原创 2025-01-09 08:10:29 · 566 阅读 · 0 评论 -
124.【C语言】数据结构之快速排序的小区间优化和非递归的解决方法
回顾文章的一般情况下快排的时间复杂度类似二叉树, 下面分析二叉树的特点注意到二叉树的最后一层节点个数为近似占总节点个数的一半(有关二叉树计算方面的知识参见文章),因此越往二叉树的下方,递归的次数越多, 一般情况下快排递归近似二叉树,如果能适当减少递归的次数,可以提高效率解决掉最后一层能减少一半递归次数,解决掉最后三层能减少的递归次数!!可以想到一个方法:越往二叉树的下方,子数组的元素个数越少,不用递归,用其他的排序方法★要注意到递归到小区间的特点,数组的大部分元素是的(即。原创 2025-01-07 21:20:34 · 1154 阅读 · 0 评论 -
123.【C语言】数据结构之快速排序挖坑法和前后指针法
虽然能完成快速排序,但该代码的可读性较差,建议专门定义一个变量hole_i表示坑位的下标,则arr[hole_i]表示坑位,可写成如下形式。2.cur找到比key(key==arr[key_i])小的值,prev++,arr[cur]和arr[prev]位置的值交换,cur++最终left和right相遇,在坑位填上key的值,单趟快速排序结束,之后对左右两个区间排序,递归处理,写成完整的挖坑法的快速排序。设key_i==0,则arr[key_i]==6,数组长度为n,对。main.c写入以下代码。原创 2025-01-05 15:29:59 · 1170 阅读 · 0 评论 -
122.【C语言】数据结构之快速排序(Hoare排序的优化)
针对121.【C语言】数据结构之快速排序(未优化的Hoare排序存在的问题)以及时间复杂度的分析文章分析出的问题,本文讲一部分问题的解决方法原创 2025-01-03 18:35:00 · 872 阅读 · 0 评论 -
121.【C语言】数据结构之快速排序(未优化的Hoare排序存在的问题)以及时间复杂度的分析
上述三种是快排最坏情况循环的次数为N+N-1+N-2+...+1,为等差数列求和,时间复杂度为。进行排序,这样导致函数的栈帧开辟的空间越来越大,函数没有没有及时返回(销毁),从而导致栈溢出。第一行排n次,第二行排(n/2)*2次,第三行排(n/3)*3次,...,第lgn行排n次。发现 a1[0]==a1[1]==a1[2]==...==a1[N-1]仔细看看测试代码1是怎么"量身定制"的:(下面展示关键代码)的数组产生栈溢出的问题,由于是递归调用,则栈溢出的原因显然是。文章的Hoare排序代码的性能(原创 2025-01-02 08:30:40 · 1361 阅读 · 0 评论 -
120.【C语言】数据结构之快速排序(详解Hoare排序算法)
③ left找到arr[left]比key小的就停止right需要找到arr[right]比key大的,之后arr[left]和arr[right]交换,left和right继续寻找,直到left>right或left==right退出。执行到Swap(&arr[key_i], &arr[left]);arr[right] == arr[key_i] 和 arr[left] == arr[key_i]时right没有变化,导致。例如对于无序数组arr={6,1,2,7,9,3,4,5,10,8},排升序。原创 2024-12-28 19:04:49 · 1436 阅读 · 0 评论 -
119.【C语言】数据结构之快速排序(调用库函数)
由于a是void*类型的,使用前应该强制类型转换为MyType类型,之后再解引用。注意到比较函数的返回类型为int(显然有三种情况,负数,0和正数)转到反汇编,查看compare函数的第一个指令的机器码和地址。测试以下代码,下断点至return 0;在内存窗口中输入0x00C613FC后发现内存窗口。size:每个元素所占的空间(类型size_t)num:数组元素的个数(类型size_t)base:指向要排序的数组(即数组名)函数没有返回值(void类型)网站给出比较函数的写法。原创 2024-12-27 19:12:15 · 946 阅读 · 0 评论 -
118.【C语言】数据结构之排序(堆排序和冒泡排序)
如果j==n-1之前数组就已经处于有序状态(即当内循环的Swap函数一次没有执行时),可以提前退出循环。注意bool exchange_flag = false;不能写在外循环的外面,否则无效。,但没有详细讲过内外循环的细节上的处理和写法上的逻辑,本文将深入讲解。之前讲过这个经验:写排序应该先写单趟排序,后将其嵌入外循环中发挥作用。例如无序数组arr={5,3,1,2}的第一次单趟排序。例如无序数组arr={5,3,1,2}的第一次单趟排序。以情况2代码为例,嵌入大循环中。以情况1代码为例,嵌入大循环中。原创 2024-12-26 23:00:45 · 752 阅读 · 0 评论 -
117.【C语言】数据结构之选择排序
因此在下一步交换前先进行判断,如果最大值出现在最左侧(即left==max_i,下标重叠),应该修改max_i的下标。给定数组int arr[]={3,5,1,6,2,3,7,9,0,8}对其使用选择排序。②将最小值和数组的第一个元素的值互换,最大值和数组的最后一个元素的值互换.如果出现left等于最大值的下标,应该将最大值的下标赋值为最小值的下标。}(结束后,下一次循环max_i==,min_i==3)-->{,最终出循环时,min_i==5,max_i==3,画图可表示为。设想的思路是否正确?原创 2024-12-25 21:43:52 · 870 阅读 · 0 评论 -
116.【C语言】测试排序性能的模板代码
1.需要包含头文件2.注意到clock的返回值为clock_t,可以看到在time.h有对clock_t的typedef,long为长整数类型,显然打印用%ld3.功能:返回处理器的消耗的时间。原创 2024-12-21 21:28:16 · 617 阅读 · 0 评论 -
115.【C语言】数据结构之排序(希尔排序)
gap = gap/3 + 1,对于任何一个数n,其n/3/3/3/3/3/3/3/3/3.....结果不为0前,三种可能:1或2,若为gap = gap/3 + 1保证循环结束后gap==1(2/3+1==1,1/3+1==1,0/3+1==1)以升序为例,如数组int* arr[]={9,1,2,5,7,4,8,6,3,5};以gap /= 2为例,初始gap==n,无论n取何值,最后一次循环gap==1,没有必要调用InsertSort。的:{1,4,7,9}、{0,6,7}、{-1,2,3}原创 2024-12-21 20:51:57 · 1201 阅读 · 0 评论 -
109.【C语言】数据结构之求二叉树的高度
将任务交给多个“下属”去做递推:整个树的高度==根节点的高度+左右子树高度中较大的高度左子树的高度==根节点的高度+其左右子树高度中较大的高度右子树的高度==根节点的高度+其左右子树高度中较大的高度......回归:当节点为NULL时(即遇到空树),回归原创 2024-12-20 19:04:32 · 1355 阅读 · 0 评论 -
114.【C语言】实战分析命令行程序:srom转换工具源码分析
1.从入口main函数开始,必须键入三个参数(argc==3),否则(argc!=3)提示使用方法"Usage: %s "之后错误返回1。因此需要对文件指针判断,文件指针为NULL,打印Error opening input file或Error opening output file最后错误返回。while ((bytes_read = fread(buffer, 1, 32, infile)) == 32) 拆分解读。文件不可打开,处于占用状态。原创 2024-12-17 14:29:52 · 1456 阅读 · 0 评论 -
113.【C语言】编写命令行程序(2)
回答文章的问题问题:既然只检查"--version"和"-v"参数(都是第二个参数),直接写成下面代码不就行了吗?能达到同样的效果,为什么需要遍历参数数组?例如:输入Commend.exe -h或Commend.exe -help来查看帮助;输入Commend.exe --host ip地址来存储主机的ip地址等等,如果参数过多,那就要手动判断argv[1],argv[2],..,argv[n]的值,有点麻烦,写成argv[i]更简单。原创 2024-12-14 17:41:15 · 1185 阅读 · 0 评论 -
112.【C语言】数据结构之排序(详解插入排序)
使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。原创 2024-12-13 20:42:07 · 1218 阅读 · 0 评论 -
110.【C语言】数据结构之判断是否为完全二叉树
根节点出栈,出栈前需要保留根节点的地址,以便于左右节点入栈(front->left和front->right,不是root->left和root->right)初始化队列-->非空树,将根节点的地址入队-->层序遍历+出栈+入栈-->对队头的值判断(为NULL则一直出队,遇到非空则销毁队列+返回false)如果写成front->left和front->right,每次循环时,front的值会改变(依据。root一直是整个二叉树根节点的地址,导致root->left和root->right的值。原创 2024-12-12 20:05:48 · 588 阅读 · 0 评论 -
109.【C语言】数据结构之二叉树层序遍历
定义:按层的方式遍历(,设n为树的深度,h==1-->h==2-->h==3-->...-->h==n)以"知识回顾"的二叉树画图分析if (root) {QueuePush(&q,root);h==3为第三层,有3,5和6;既存储了树的节点的地址又存储了下一个节点的地址(这样做方便操作)可以看到QueuePop的free(pq->head);遍历顺序:1-->2-->4-->3-->5-->6。核心思想:先出队一个根节点,后将根的左右非空节点入队。这里用的是队列,画图分析上方二叉树的层序遍历。原创 2024-12-08 20:27:55 · 534 阅读 · 0 评论 -
98.【C语言】数据结构之队列
Queue.h写入int size;}Queue;除了有头指针和尾指针之外,还要用变量size来存储队列的大小再用一个结构体去定义队列中的每一个节点}QNode;这里和以往的链表的定义不一样,用两个结构体来定义 ,将头指针,尾指针和size打包成结构体是为了方便操作。原创 2024-12-05 18:53:09 · 1428 阅读 · 0 评论 -
44.5.【C语言】辨析“数组指针”和“指针数组”
发现存储的元素的值是地址0x00e47bcc,0x00e47bd0,0x00e47bd4,0x00e47bd8,0x00e47bdc。注意到"offset string",是将字符串的地址存储到数组中,因此顾名思义,为指针数组。其中a就是数组指针,因为数组名代表数组首元素的地址,该数组名指向数组的首元素A。由指针数组的定义,如果存储一级指针,则就要定义类型为二级指针的数组来存储。从语文的角度理解,"数组"修饰"指针".因此数组指针是指针。从语文的角度理解,"指针"修饰"数组".因此指针数组是数组。原创 2024-12-05 18:34:48 · 396 阅读 · 0 评论 -
108.【C语言】数据结构之二叉树查找值为x的节点
查找值为x的节点并返回节点的地址。有详细的递归调用展开图原创 2024-12-01 12:11:46 · 744 阅读 · 0 评论 -
107.【C语言】数据结构之二叉树求总节点和第K层节点的个数
答:不可以,理由1:无论函数调用多少次,写在函数内的静态变量只会被初始化一次,即第二,三,四,...次调用不会初始化.理由2:在函数外部无法访问静态变量。原创 2024-11-29 21:05:32 · 1630 阅读 · 0 评论 -
106.【C语言】数据结构之二叉树的三种递归遍历方式
在文章中提到:任何一棵树都由两部分构成:根和子树,子树又由根和子树构成因此看见二叉树要本能地做出反应:拆成三部分:根,左子树和右子树,直到遇到空树(叶节点)则停止拆分。原创 2024-11-27 20:08:08 · 1790 阅读 · 0 评论 -
105.【C语言】数据结构之TopK问题详细分析
TopK即排名位于前K个(按从大到小或从小到大排序)原创 2024-11-26 19:11:39 · 1196 阅读 · 0 评论 -
104.【C语言】数据结构之建堆的时间复杂度分析
用堆对数组进行排序,排升序建大堆的时间复杂度总为对比//向上调整建堆时间复杂度为O(N*logN)i < n;i++)//排序的时间复杂度为O(N*logN)end--;和//向下调整建堆时间复杂度为O(N)i >= 0;i--)//排序的时间复杂度为O(N*logN)end--;注意(n-1-1)/2这里把(n-1)视作整体2%5E02%5E12%5E22%5E3...+...+...+原创 2024-11-24 20:14:52 · 977 阅读 · 0 评论 -
103.【C语言】数据结构之用堆对数组排序
向上调整:向下调整:建大根堆还是小根堆?由小根堆的定义:树中所有的父节点的值都小于或等于孩子节点的值,这样排出来的数组时升序的,建小根堆调用向上调整函数即可(把画圈的地方改成原创 2024-11-24 19:04:48 · 564 阅读 · 0 评论 -
102.【C语言】数据结构之二叉树的堆实现(顺序结构) 2
尾删没有任何意义,删头才有意义(即删),删除之后要调整二叉树,仍然符合大根堆的性质拿上图举例,现删除堆顶元素50。原创 2024-11-22 19:13:49 · 1274 阅读 · 0 评论 -
101.【C语言】数据结构之二叉树的堆实现(顺序结构) 1
1.2.可以用结构体来定义堆,由于堆的底层是用数组存储的,因此三个成员变量:数据域,大小size,容量capacity写入头文件中int size;}HP;原创 2024-11-20 19:44:29 · 1473 阅读 · 0 评论 -
100.【C语言】数据结构之二叉树的基本知识
非线性数据结构(线性的数据结构:顺序表、链表和队列),结构类似倒过来的树(根朝上叶朝下任何一棵树都由两部分构成:根和子树,子树又由根和子树构成......int data;或者使用数组int data;上述两种定义的方法不高效,需要手动设置多个结点,而且只针对于N已知的情况,其实使用"左孩子+右兄弟"的方法更简单例如下面这个二叉树用"左孩子+右兄弟"方法画图。原创 2024-11-18 21:22:54 · 982 阅读 · 0 评论 -
99.【C语言】数据结构之栈
栈1.基本概念2.提炼要点3.概念选择题4.栈的实现 栈初始化函数 入栈函数 出栈函数和栈顶函数栈销毁函数原创 2024-11-14 19:02:37 · 1512 阅读 · 0 评论 -
98.【C语言】存储体系结构
中,由于数组在本质上是一块连续的内存空间,因此缓存的命中率高,链表靠指针访问,不连续,,因此缓存的命中率低(缓冲污染:加载了没用的数据,对于链表的访问会经常发生)当想对顺序表或链表的每个位置进行遍历访问(读或写)时,CPU会读取缓存中的数据,如果缓存中有顺序表或链表的数据,则称为。,而且一次性会加载多个字节(具体加载多少和硬件有关)缓存分三级:速度:一级>二级>三级。文章提到了数据结构的定义: 数据在。,若不命中,CPU会要求将。缓存的大小原创 2024-11-10 11:20:56 · 449 阅读 · 0 评论 -
96.【C语言】解析预处理(4)
if defined(symbol)等价写法为#ifdef symbol#if!defined(symbol)等价写法为#ifndef symbol例如微软的<stdlib.h>中有如下代码#endif(#ifndef全称if not define)解释:如果没有定义 _countof,则定义#define_countof __crt_countof。原创 2025-02-25 19:35:01 · 829 阅读 · 0 评论 -
97.【C语言】数据结构之双向链表的头插,头删,查找,中间插入,中间删除和销毁函数
1.双向链表的头插 方法一 方法二2.双向链表的头删3.双向链表的销毁4.双向链表的某个节点的数据查找5.双向链表的中间插入5.双向链表的中间删除6.对比顺序表和链表原创 2024-11-10 10:46:48 · 856 阅读 · 0 评论 -
96.【C语言】数据结构之双向链表的初始化,尾插,打印和尾删
1.双向链表2.结构体的定义3.示意图3.代码示例1.双向链表的尾插示意图代码main.cList.hList.c详细分析代码的执行过程双向链表的初始化2.双向链表的打印代码3.双向链表的尾删原创 2024-11-09 16:10:11 · 1310 阅读 · 0 评论 -
94.【C语言】解析预处理(2)
(a) : (b) )中a出现两次),如果参数带有副作用,那么你在使用这个宏的时候就可能出现危险,导致不可预测的后果。2.再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号,MAX(x,10)被替换为( (x) > (10)?1.首先对参数进行检查,MAX(x,NUM)的NUM首先被替换,之后为MAX(x,10);2.参数类型上:函数需要指定参数的类型,而宏的参数和类型无关(这里体现出宏的缺点,不严谨)执行(x++) > (y++)后, 还要执行y++,这里y加了两次,为副作用的体现。原创 2024-12-01 17:00:33 · 1068 阅读 · 0 评论