- 博客(22)
- 收藏
- 关注
原创 2021-09-26
标题: 希尔排序(C语言实现) 本篇博客主要是思路的分享,代码的解释很少。 希尔排序是效率很高的排序, 它是直接插入排序的变形和优化。所以直接插入排序和希尔排序都属于插入排序。 想要看的懂这篇博客,首先你需要了解直接插入排序, 抱歉的是我还没有写关于直接插入排序的博客,所以我直接将写好的代码拿出来: 希尔排序的思路: 那怎么进行 预排序 呢? 几趟插入下来,数据已经接近有序了。 直接插入排序是针对间隔为1的元素,也就是gap为1,而希尔排序是针对间隔大于1的元素,也就是gap > 1
2021-10-01 19:04:43 86
原创 2021-09-05
标题:C语言结构体中的【柔性数组】成员 C99标准中, 允许结构体中的最后一个成员变量是一个未知大小的数组,这就是【柔性数组】成员。它的声明如下: struct S { int a; int arr[];//柔性数组成员,这是一种声明方式 }; struct S { int a; int arr[0]//这是另外一种声明方式 } 有些编译器支持第一种,有些编译器支持第二种,当然像VS2019的话都支持。 柔性数组成员有以下几个特点: 1、【柔性数组】成员的前面必须至少有一个其
2021-09-05 14:26:40 114
原创 2021-08-15
标题:现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针(C语言实现) 这道题的难度是较难,但是思想却很简单,我们把小于 x 的放在一个链表中,大于 x 的放在一个链表中,然后再将这两个链表合并。 我们假设 x 的值是 10,将小于 x 的结点放在 lessHead( lessHead 是头结点) 和 lessTail 后面,然后把 cur 更新成 lessTail (方便下次尾插找
2021-08-15 14:42:33 107
原创 2021-08-15
标题:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。(C语言实现) 这道题的思路是很简单的,将值小的结点拿下来尾插就可以了。 以下是代码的实现: 但是,上面的代码有一些不好的地方,比如每次进入循环,都需要判断一次 tail 是否为 NULL, 实际是,只有第一次 tail才会为 NULL, 所以思路一是将值小的那个结点做头结点,这样只需判断一次就可以了。下面给出代码: 以上是一种优化思路,现在给出思路二,我们 malloc 出来一个结点称作哨兵
2021-08-15 12:52:40 73
原创 2021-08-14
标题: 输入一个链表,输出该链表中倒数第 k 个结点(牛客网,C语言实现) 题目的思路如下: 先让 fast 走 k 步 : fast 和 slow 同时走 : fast 走到 NULL 后, slow 正好走到倒数第 k 个结点 代码如下: struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) { // write code here struct ListNode* slow = pListHead
2021-08-14 13:34:15 124
原创 2021-08-02
标题:现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。(牛客网,C语言实现) 这道题的解题思路分成三步: 1.把链表中 val 值小于 x 的,尾插到一个链上。 2.把链表中 val 值大于 x 。的,尾插到一个链上。 3.把这两个链,链接在一起。 假如链表如下: 首先 malloc 两个哨兵位的头结点,不存放任何数据,待处理完后,删除掉。一个头结点取名为 lessHead, 用来链接
2021-08-02 16:29:48 76
原创 2021-08-01
标题:LeetCode:给定一个带有头结点head的非空链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。 给两个指针变量,一个slow,一个fast,它们都指向头结点。 slow指针变量每次走一步,fast指针变量每次走两步。 fast走到最后一个结点的时候,slow正好走到中间结点。 以上是链表的结点个数是奇数的情况,是奇数的时候,fast走到最后一个结点的位置就可以停下了。那么链表的结点是偶数的情况呢? slow指针还是每次走一步,fast指针还是每次走两步。 链表的
2021-08-01 16:10:31 74
原创 2021-07-10
标题:C语言实现斐波那契数列(递归版本与非递归版本) 斐波那契数列就是:后一项等于前两项之和 。 但是 ,前两项很特殊 ,是 1 ,也就是在计算第 n 个斐波那契数列时,如果 n = 2 ,返回值应该是 1 。 如果 n > 2 , 那么计算第 n 项斐波那契数列时,就应该将前两项和相加 。 递归版本 : 非递归版本 : 对于非递归版本 , 可以这样理解 : 非递归的意义在于,它的效率更高,当 n 比较大的时候 , 递归的程序运行的很慢,耗费时间 。 当然了,递归也有自己的优势 ,
2021-07-10 13:47:16 64
原创 2021-06-12
标题:C语言中的位段 位段是什么??? 位段是依附于结构体的,对于上图的位段,如果把冒号和数字去掉,其实就是结构体。 位段的声明和结构体的声明有两个不同: 1.位段的成员必须是int unsigned int 或者 char。 2.位段的成员名后面有一个冒号和一个数字。 那么冒号后面的数字是什么意思呢,是字节大小??? 是占几个bit位的意思。。。。。 我们定义一个人这个复杂对象的结构体类型,假如这里面包括一个性别的成员变量,性别的最多有三种类型:男 女 和保密 00 代表男 01 代表女 10 代表保
2021-06-12 20:53:38 71
原创 2021-06-11
标题:如何计算结构体的大小?? 上图中结构体的大小是多少呢?你可能会说是6个字节大小,char类型占1个字节,int类型占4个字节,所以是6个字节。 然而运行结果却是8个字节,为什么呢???? 这就是结构体对齐: 1.第一个成员在与结构体变量偏移量为0的地址处。 2.其他成员变量对齐到某个数字(对齐数)的整数倍处。 对齐数:编译器默认的对齐数与结成员大小的较小值,VS2019的默认对齐数是8 3.结构体的总大小是所有成员对齐数中最大对齐数的整数倍。 1.char c1是第一个成员,它在偏移量为0的地址
2021-06-11 15:41:48 116
原创 2021-06-10
标题:用C语言实现库函数memmove void* memmove(void* dest,const void* src,size_t num) 在上一篇博客中提到,mommove函数可以帮我们 拷贝重叠内存空间的数据,也可以帮我们拷贝不重叠内存空间的数据,所以mommove函数的实现是包括 memcpy函数的实现的,那么我们就不在讨论不重叠内存空间的情况了。 以下,我们以图的方式说明重叠内存空间的情况: 这是第一种情形,当dest的地址在src地址的前面,也就是dest <src的情况,这
2021-06-10 19:08:06 118
原创 2021-06-10
标题:模拟实现C语言库函数memcpy和mommove memcpy的功能是内存拷贝 void* memcpy(void* dest,const void* src,size_t num) 1.第一个参数是目的空间的地址,就是要拷贝在哪的地方。 2.第二个参数是源空间的地址,就是要拷贝内容的地址。 3.size_t num是要拷贝的字节数,因为前两个参数都是void* 所以必须要在知道拷贝多大的内存空间。 my_memcpy的实现: void* my_memcpy(void* dest,const
2021-06-10 17:30:04 64
原创 2021-06-08
标题:深度分析C语言库函数strtok strtok是C语言中的库函数,它的功能是切割字符串。 这是strtok的原型: char* strtok(char* str,const char* seq) 1.strtok的第一个参数是一个字符串,它包含了0个或者多个 由seq字符串中一个或者多个分隔符分隔的标记。 2.第二个参数seq也是一个字符串,它的内容是要分割的字符串 中的分隔符。 举个例子吧: int main() { char str1[] = "zsj@qq.com
2021-06-08 16:00:13 73
原创 2021-06-04
标题:用C语言实现strlen库函数! 1.计数器版本 size_t my_strlen(const char* str) { assert(str != NULL); int count = 0; while(*str != '\0') { count++; str++; } return count; } 2.递归版本 size_t my_strlen(const char* str) { assert(str)
2021-06-07 16:01:26 57
原创 2021-05-15
栈区内存使用习惯 代码运行的结果是什么呢? 这个代码有很明显的错误,那就是非法访问内存,你的第一反应应该是程序崩溃。 但是,实际的运行结果却是: 没错,是死循环!!!! 变量i和数组arr都是局部变量 局部变量都是在栈区创建的 栈区内存的使用习惯是: 先使用高地址再使用低地址。 数组随着下标的增长,地址是由低到高。 arr[12]和i的地址是一样的 所以把arr[12]置为0的时候,实际上就是把变量i置为0,那么0又小于12,就会在屏幕上打印11个hello,等到把arr[12]置为0的时候,i又变
2021-05-15 20:14:40 68
原创 2021-04-03
标题:VS2019的登录 **VS2019的试用期三十天后,需要登录微软账号才可继续使用,很多人登录不上,便用尽网上的招数,我自己就是。 其实可以考虑一下浏览器的问题,我当初一直登录不上,应该是因为我把搜狗高速浏览器当成默认浏览器了,后来换了微软的浏览器,立马就登录上了。** ...
2021-04-03 15:31:17 146
原创 2021-03-21
标题:大小端的判断 写一段程序,判断当前编译器的存储模式是大端字节序还是小端字节序。 #include<stdio.h> int main() { int a=1; if(1==*(char*)&a) { printf("小端\n"); } else { printf("大端\n"); } return 0; } 1在内存中的表示为 :0x00000001 如果编译器采用的是小端模式即:数据的低位保存在内存
2021-03-21 13:48:32 61
原创 2021-03-15
标题:模拟实现my_strstr #include<stdio.h> #include<assert.h> char* my_strstr(const char* p1,const char* p2) { assert(p1!=NULL); assert(p2!=NULL); char* s1=NULL: char* s2=NULL; char* cur=(char*)p1; if(*p2=='\0') { //p
2021-03-15 16:38:51 74
原创 2021-03-14
标题:my_strcpy 我们先了解一下strcpy这个函数吧 char* strcpy(char* destination,const char* source) 注意:源字符串必须以\0结束 会将源字符串中的\0拷贝到目标空间 目标空间必须足够大,以确保能存放源字符串 目标空间必须可变 #include<stdio.h> #include<assert.h> char* my_strcpy(char* dest,const char* src) { assert(dest!
2021-03-14 10:18:18 61
原创 2021-03-13
标题:杨氏矩阵 有一个数字矩阵,这个矩阵的每行从左往右,从上往下都是递增的,请编写程序,在这样的矩阵中查找某个数字是否存在。要求:时间复杂度要小于O(n) #include<stdio.h> int FindNum(int arr[3][3],int k,int* px,int* py) { while(x>=0&&y<=*py-1) { int x=0; int y=*py-1;//x和y是行和列,找到矩阵中右上角的那个值 if(a
2021-03-13 16:54:06 258
原创 2021-03-12
左旋字符串 写一个函数,可以左旋字符串中的k个字符,例如:ABCD左旋一个字符得到BCDA,左旋两个字符串后得到CDAB。 #include<stdio.h> #include<string.h> #include<assert.h> void reverse(char* left,char* right) { assert(left!=NULL); assert(right!=NULL); while(left<right) { char tmp=*l
2021-03-12 11:13:16 125 2
原创 我的第一篇博客
标题:找到killer 我的第一篇博客,就分享一段刚学到的代码吧! 题目:日本某地发生了一件谋杀事件,警察通过排查确定杀人凶手必为4个嫌疑犯中的一个。 A :不是我 B:是C C:是D D:C在胡说 其中3个人说了真话,1个人说了假话。写一段程序,找到凶手。 #include<stdio.h> int main() { int killer=0; //采用假设的方法,分别假设ABCD是凶手 for(killer='a';killer<'d';killer++)
2021-03-10 20:13:54 60
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人