基本数据结构与算法(C语言版本)
文章平均质量分 66
不同于 C++,Java这些更高级的语言,有大量的库可以调用,C 语言给我们提供了基本的思想,需要我们自己造车。这些我们自己写的库在后续编程中即可方便的粘贴使用。
mrbone9
文章不定时更新,都是自己学习过程的记录
没有水文都是干货
换了工作比较事多,更新放缓
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
C语言的hashmap
在算法练习当中,常常会遇到用 hashmap 来实现的思路,通过 key-value 方便快捷的查找,增加,删除特定数据。在高级语言当中,c++或java都有一套 hashmap API可供使用,但是 C 语言却没有系统的不过开源项目为我们提供了这套工具,利用这套工具,可以方便的将自定义数据结构 hash 话官网文档:uthashhttps://troydhanson.github.io/uthash/userguide.html#_a_hash_in_cgit 仓库uthash原创 2022-03-28 21:20:58 · 4400 阅读 · 0 评论 -
排序算法之快速排序
在讲解 快速排序 之前,我们提前引入了两个问题:快速排序基石之荷兰国旗问题快速排序基石之荷兰国旗问题II如果你还未研读上面的两个题目,建议先研习一下,因为我们这章要讲解的快速排序原理就是基于上面两个问题的解决方式来做的快速排序可以分为 3 个版本:1.0 版本:荷兰国旗问题固定选择最末元素为 num 值,保证 num 前的数组内容分为两部分完成后 num 与 >num 区域的第一个元素交换,这样 num 确定好了位置剩余就是递归新的两部分代码部分:原创 2022-03-21 22:54:38 · 349 阅读 · 0 评论 -
快速排序基石之荷兰国旗问题II
在上一章我们讲解了快速排序基石之荷兰国旗问题这一章我们在此基础上继续扩展题目一:给定一个数组 arr,一个数 num,请把小于等于 num 的数放在数组的左边,等于 num 的数放在数组中间,大于 num 的数放在数组的右边。要求额外空间复杂度 O(1),时间复杂度 O(N)思路:以 num 为界把数组分为三部分:1. 左侧 <= num 区域2. 中间 == num 区域3. 右侧 >= num 区域那么我们可以设定一个边界的 idx,当前元.原创 2022-03-20 15:45:14 · 1205 阅读 · 0 评论 -
快速排序基石之荷兰国旗问题
题目一:给定一个数组 arr,一个数 num,请把小于等于 num 的数放在数组的左边,大于 num 的数放在数组的右边。要求额外空间复杂度 O(1),时间复杂度 O(N)思路:以 num 为界把数组分为两部分:1. 左侧 <= num 区域2. 右侧 >= num 区域那么我们可以设定一个边界的 idx,当前元素与 num 进行比较:1. 如果 [i] <= num,边界右侧的元素与 [i] 之间的元素是 > num 的元素,所以我们首先要将原创 2022-03-20 12:17:01 · 1338 阅读 · 0 评论 -
归并排序示例:小和问题
题目:在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和示例:[1,3,4,2,5]1:左边没有比 1 小的数。小和 = 03:左边比 3 小的数有 1。小和 = 1 * 14:左边比 4 小的数有 1,3。小和 = 1 * 1 + 1 * 32: 左边比 2 小的数有 1。 小和 = 1 * 15: 左边比 5 小的数有 1,3,4,2。 小和 = 1 * 1 + 1 * 3 + 1 * 4 + 1 * 2总共结果 = 1 + 1 + 3 + 1 +原创 2022-03-19 16:30:42 · 643 阅读 · 0 评论 -
时间复杂度之 Master 公式
递归行为时间复杂度的估算:示例: 求一个数组的最大值arr[]={3,5,6,2,8,3}分别求左侧最大值,右侧最大值,最后返回两侧最大值比较后的最大值int doGetMaxnum(int *arr, int l, int r){ if(l == r) return arr[l]; int mid = l + ( (r - l)>>1); int leftMax = doGetMaxnum(arr, l, mid); int rightMax = doGetM.原创 2022-03-19 10:41:35 · 802 阅读 · 0 评论 -
排序算法之归并排序
合并算法的基本思想:就是两个有序子集之间通过合并成一个大的有序集然后合并的这个大的有序集再与另一个大的有序集继续合并成更大的有序集直到完成整个数组的有序举个例子:数组 [5,3,2,6]1. 划分为两个子集2. 分别有序化3. 合并过程,分别用两个指针,依次对比子集间的元素大小,填充到额外的空间4. 将有序话的额外空间再次填充回原数组过程 2 其实就是 过程 1,3,4 的一个过程我们来看下代码实现:把数组一分为二,分别对左边,右边排序,最后再原创 2022-03-19 09:49:48 · 450 阅读 · 0 评论 -
排序算法之插入排序
插入排序相对于前面的:选择排序,冒泡排序 来讲是一个变化前面两种排序算法,时间复杂度都是 O(N^2),因为每一个元素都需要跟其余元素比较一次但是插入排序就不一样了,时间复杂度 O(logN),我们来看下为什么想象打斗地主这类棋牌游戏,新摸一张牌我们需要将其 插入 到适当的位置,比如:从右至左,依次与手牌比较,如果比手牌位置小,就左移一个位置插入排序也是这样的顺序,这样对于一个新的元素来讲,不一定需要完全与所有元素比较一次当插入完成后,0 ~ 当前位置就是有序的示例:原创 2022-03-14 10:00:38 · 4990 阅读 · 0 评论 -
排序算法之冒泡排序
相信大多数初学者都是从冒泡排序入手的,那么今日就算是复盘,加深一下印象概念:从元素 0 开始,与元素 1 比较,如果 0 > 1,那么交换接着元素 1 与 元素 2 比较,如果 1 > 2 ,交换依次进行相邻数的比较,这样一轮下来,最大之就排到最末位置下一轮接着从 0 开始,直到末尾位置 -1 ,如此循环示例:{3,5,6,2,2,3,4,1} 3<>5 {3,5,6,2,2,3,4,1} 5<>6 {3,5,6,2原创 2022-03-14 09:48:35 · 500 阅读 · 0 评论 -
排序算法之选择排序
先来一个简单的排序算法:选择排序概念:数组元素从 0 开始,依次与后面的元素比较,找到这一轮的最小值,然后与 0 元素交换这样最小值就到了 0 元素从 1 开始,依次与后面的元素比较,找到这一轮的最小值,然后与 1 元素交换这样最小值就到了 1 元素如此循环,每一次都能找到最小值,然后进行一个交换,这个过程就是 选择最小值的过程示例:{3,5,6,2,2,3,4,1} 1 <> 3 {1,5,6,...原创 2022-03-14 08:35:58 · 1783 阅读 · 0 评论 -
排序算法之堆排序
堆排序是一种基于二叉堆数据结构的排序算法二叉树:是 n(n >= 0)个结点的有限集合,该集合或为空集(空二叉树)。或者由一个根节点喝两颗互不相交的,分别称为根节点的左子树和右子树的二叉树组成满二叉树:除了叶子节点,每个结点的度都是2。或者形象来讲,所有叶子节点都排满的二叉树完全二叉树:节点排序顺序能够完全对应满二叉树的二叉树既然完全二叉树是依序号排列,那么就可以用一维数组来保存,譬如1 2 3 4 5 6 [o] ...原创 2022-01-14 14:10:30 · 301 阅读 · 0 评论 -
排序算法之计数排序
在以往的排序算法里面,很多时候都是进行元素之间的比较,再移动位置而计数排序确不需要进行元素间比较考虑一个一维数组,其下标是依序递增,那么假设我们的待排序元素 最大值 是 k,我们的一维数组恰好有 k + 1 的长度元素值 k 可以在一维数组 [k] 几个数,如果存有 n 个 元素值为 k,那么 [k] 的值就是 n同样,其余元素分别统计个数后填入这个一维数组对应的下标完成所有元素的统计和填值后,我们的这个一维数组就清楚的知道整个元素的分布情况并且,最爽的时,数组已经是升序排列了原创 2022-01-14 17:52:37 · 323 阅读 · 0 评论 -
二叉树之AVL树
今天来细说下 AVL 树,并结合图示代码来认识并掌握 AVL 树的创建,删除,体会下 AVL 特有的自平衡性。本文涉及比较多的内容,鉴于时间关系,当你看到时可能是未完结章节,尽情期待目录:AVL 概念AVL 的旋转AVL 树代码实现(C语言)测试实例AVL 概念AVL 也是二叉树的一种,所以符合所有二叉树应有的特性,以及遍历方法与二叉树不同的是,AVL树是一颗平衡树:节点 root,左子节点的高度 与 右子节点的高度,最大差值 = 1下面看看 AV原创 2022-03-09 23:15:45 · 877 阅读 · 0 评论 -
二叉树遍历之morris遍历
我们在遍历树时使用的 递归遍历 或者 迭代遍历,其实都是用到了堆栈来存储,增加了空间复杂度有没有办法连这个空间都不要额外分配呢?考虑一棵树:1. 如果有 N 个节点,那么就有 2N 个指针(分别指向左子节点,右子节点)2. 每一个节点,其实只有 1 个指针指向他,根节点没有节点指向,那么用到的指针个数:N-13. 结合1,2我们可以得知,还有 2N - (N - 1) = N + 1 个指针是空闲的 比如节点可能有 0,1,2个子节点,对应空闲指针 2,1,0 个如果...原创 2022-02-21 14:58:50 · 518 阅读 · 0 评论 -
二叉树遍历之层序遍历
不同于二叉树遍历之递归遍历和二叉树遍历之迭代遍历我们还可以采用每一层的遍历顺序来访问树的节点考虑一个问题:访问完左子节点如何能够访问右子节点呢,他们是平级关系,兄弟节点如若要访问,势必要再次利用父节点作为过渡,那么当这个树特别大时,还要来回的从 最左子节点<>根节点 <> 最右子节点,这是不现实的如何解决:方法一、队列方式 111. 二叉树的最小深度文章的广度优先算法内容方法二、数组方式 如果我们...原创 2022-02-19 23:05:07 · 278 阅读 · 0 评论 -
二叉树遍历之迭代遍历
前文我们简述了二叉树遍历之递归遍历其实用到的是递归中自己的栈来完成的,那么我们要是用迭代的话也是要通过自己的栈来完成前序遍历:根 左 右我们在递归遍历时通过前序遍历的原理图示展示了整个过程:根节点第一次出栈就可以打印了,然后再来分别出栈左右子节点void preorderIteration(struct TreeNode* root, MyStack *stk){ if(root == NULL) return; myStackPush(stk, root); .原创 2022-02-19 22:31:15 · 627 阅读 · 0 评论 -
二叉树遍历之递归遍历
前文二叉树的实现简单讲解了基本概念,创建一颗树的过程遍历整棵树最常用的还是递归遍历,代码实现容易遍历顺序:谈及遍历,通常为操作该节点,比如打印节点值;而经过并不是遍历的意思前序遍历:根,左,右 中序遍历:左,根,右 后序遍历:左,右,根 实现原理: 以前序遍历为例,顺序为:根,左,右 1. 根节点入栈 2. 开启循环,每次出栈一元素,打印其值;...原创 2022-02-19 18:15:18 · 1121 阅读 · 0 评论 -
二叉树的实现
在回忆学生时代学习树这种数据结构时,仅有的回忆就是前中后遍历,其余毫无印记在工作当中,好像就没有怎么用到,更不用说编码去实现,调试其实不然,AVL树,红黑树等等都是有实际的应用,所以掌握好基本的知识点还是非常必要的以最简单常用的基础开始树的表现:链表 的形式最为常见,因为树是有分支的,是 非线性的正如自然界的树,只不过树根在上,分支在下,最末为叶子我们研究的都是基于 二叉树二叉树:是 n(n >= 0)个结点的有限集合,该集合或为空集(空二叉树)。或者由一个根节点和原创 2022-02-19 17:28:27 · 876 阅读 · 1 评论 -
堆栈的实现
堆栈的表现:可以直接使用一维数组来做堆栈堆栈的操作:入栈:新的元素放到堆栈中出栈:把堆栈中的元素移除堆栈存在三个个变量:typedef struct { struct TreeNode **stk; int stkSize; int stkCapacity;} MyStack;**stk:这个例子我们存放的是树节点指针,所以用二维数组表示 如果一般的比如整形变量,用一维数组即可,像这样typedef struct {...原创 2022-02-19 10:09:15 · 1148 阅读 · 0 评论 -
基本数据结构与算法(C 语言版本)
持续完成基本数据结构的理论讲解,图示说明,以及相关实现实现代码可以方便的当作 API 库代码粘贴使用,或加以改进文章目录:队列的实现原创 2022-02-18 20:46:26 · 599 阅读 · 0 评论 -
队列的实现
队列的表现:一维数组是队列的直接表现,我们可以直接使用一维数组来做队列另外,我们也可以使用堆栈来实现队列队列的操作:入队:新的元素要放置到队列中出队:把队列中的元素移出队列存在两个序列变量:front, rear 分别指代队列头以及队列末入队操作将新的元素放到 rear 位置,rear指向其后位置出队操作将 front 位置的元素移出队列,front指向其后位置初始化 front,rear 指向首元素空位当front,rear再次相等时表面队列为空队列的.原创 2022-02-18 20:43:10 · 448 阅读 · 0 评论
分享