数据结构与算法
文章平均质量分 53
掌握数据结构与算法,走遍天下都不怕
杨·戬
孤舟蓑笠翁 独钓寒江雪
展开
-
树之手撕红黑树
简单说一下二叉搜索树与AVL树要学红黑树,首先你必须学会二叉搜索树,也就是二叉查找树,如果不会的同学,可以去看我写过的文章里面有那么这里我们来说一下AVL树他就是一个平衡二叉搜索树,什么叫平衡呢,就是一棵树维持一个稳定的二叉状态,维持一个稳定的高度,高度稳定了,它的查找时间复杂度也就低了,那么AVL树就是一个利用左右子树高度之差小于等于1的这样一个平衡因子来维持的树的平衡,一旦左右子树高度之差大于1,那么树就是开始旋转。下面来简单对比一下二叉搜索树和AVL树。原创 2023-11-18 00:29:58 · 356 阅读 · 0 评论 -
树之二叉排序树(二叉搜索树)
第三种情况:你删除的结点下面就是说还有左右子树,那么这个时候,我们就要去找到这棵树中序遍历结果之后的直接前驱或者直接后继,然后把这个前驱或者后继给按到删除结点这个位置上,将它下面的树移到被替换结点的位置。在上代码之前,先来说一下,二叉搜索树很多方法都利用了递归的思想,许多说明我都放到代码注释里面了,可以结合下面的这张图进行思维分析。再来看java的运行代码(algorithm/bst1)构造树的过程即是对无序序列进行排序的过程。通常采用二叉链表作为存储结构 不能。插入的新节点是以叶子形式进行插入的。原创 2023-11-11 07:57:28 · 214 阅读 · 0 评论 -
深度剖析堆栈指针
表达式3: printf("%d %d %d\n",(*pp_root)->left,root->left,&child->value);表达式1:printf("%d %d %d %d\n",&(*root),root,&root->value,&root);以前我写过一句话,就是说,如果看到一个*变量,那就是直逼这个变量所保存的内存地址,然后取出里面保存的对应的值或者地址,表达式2:printf("%d %d\n",&(*pp_root)->left,&root->left);这也就是它报错的原因。原创 2023-08-13 02:00:11 · 229 阅读 · 0 评论 -
循环链表之两个循环链表合并
针对于上面这个问题,如果是两张单链表合并该怎么做 话不多说,直接上代码main.c上面还是用了自己的库,不会的去看我的linux之动态库与静态库的制作运行结果:然后做一个简要分析:上面两张单链表合并,其中某一张单链表就会循环到尾部,然后在从尾部链接下一个单链表的头结点 ,这个就会存在一个O(n)的时间复杂度那么如果用循环链表是什么样子呢?或者说它的时间复杂度会是一个什么情况这里先来说一个设计思想话不多说,直接上代码main1.c 运行结果:拿出核心代码看一下 静态链表的合并,并不需要像单链表一样原创 2022-12-04 00:33:33 · 1026 阅读 · 0 评论 -
静态链表习题初入门之(A-B)∪(B-A)
题目:在终端输入集合元素,先建立表示集合A的静态链表S,然后输入集合B的元素,同时查找S表。若存在和B相同的元素,则从S表中删除,否则将此元素插入S中。之前把静态链表的代码做成一个动态库,直接拿来用即可,不会做动态库与静态库或者不会写静态链表的同学可以直接去查看我的Linux动态库与静态库制作的文章。换句话说:就是把两个集合重叠在一起,但是没有重复元素。用一张图来说明(A-B)∪(B-A)下面直接上代码main.c。原创 2022-11-24 19:54:12 · 300 阅读 · 0 评论 -
算法的时间复杂度分析
评估一个算法的效率,不能使用什么实时的计量单位,比如秒啊,微妙啊啥的,最好用逻辑单位,他能表示数据规模N与时间t的这样一种关系,然后分析这种关系的一种增长曲线一般一个算法我们都会用函数来表示,一般我们取函数项里面增长最快的一项。因为我们考虑算法的时候,主要就是考虑问题规模特别大的时候,小数据规模,你的算法是什么时间复杂度,影响都没有多大,这也是我们经常分析问题的一种思维,考虑问题,我们一般要考虑最坏的情况。函数增长最快一项与问题规模特别大这个其实相互独立,每一个函数问题规模都可以增大,也都有增长速率原创 2020-11-28 01:38:59 · 2661 阅读 · 1 评论 -
图之广度优先遍历
这是另外一个遍历图中所有顶点的方法,名字叫广度优先遍历(Breadth first search),下面就来说一下这个遍历的具体思路。首选先我们来看一张图:乍一看这个图,特别凌乱,好像除了用深度优先遍历之后,就没有什么思路。但是我们可以把这张图进行如下的一个整理 这样子一看是不是觉得特别有层次感,但是每一个顶点相连的邻接点也没有乱,比如A就是第一层,BF就是第二层,CIGE就是第三层,DH就是第四层,那么最后这张图的打印顺序就是ABFCIGEDH那么下面我用下面一张图来分析一下它的具体思路:还是用一张图来讲原创 2022-07-04 12:12:43 · 349 阅读 · 0 评论 -
图之深度优先遍历
就是说,怎么遍历一个图结构,那么这里就有前辈给我们提供了一个思路,叫深度优先搜索,也就是DFS(Depth First Search):它的思路:假设我们这里的图就是一张树的结构其实对于一张图的深度遍历,还是采用的递归的思想来做: 在来看具体递归分析过程: 话不多说,直接上代码,下面就是对于一个无向图的邻接矩阵的实现遍历undirected_graph.cpp运行结果:好了,这就是邻接矩阵无向图的深度优先搜索,有向图也是一样的操作,这是不是就类似于一棵二叉树的前序遍历,但是这个只是对于这个邻接矩阵来说原创 2022-07-03 15:56:59 · 280 阅读 · 0 评论 -
图的存储结构
这个也就是怎么在内存中表示一张图第一种方式:采用邻接矩阵来表示一张图 简单来说就是,采用二个数组来表示一张图 1.第一个数组:用一维数组来存储图中的顶点信息 2.第二个数组:用二维数组存储图中的边与弧的信息 先来说无向图的邻接矩阵表示方法: 来说一下这个二维矩阵,横向与纵向都代表这个图中的顶点,这样做,有助于来分析两个顶点的关系,比如方向(v1,v2)这个就很符合二维数组ar原创 2022-06-27 16:05:33 · 543 阅读 · 0 评论 -
图的基本概念以及相关定义
先来看几个单词:1.2.3. 4. 再来说下面几个概念: 1.图: 顶点的有穷非空集合和顶点之间边的集合组成,通常表示为G=(V,E),G表示一个图,V表示顶点的集合,E表示边的集合 2.无向边与有向边: 无向边:比如从顶点v1到v2的边没有方向,则称这条边为无向边,用无序偶对(v1,v2)表示 有向边:从顶点v1到v2有有方向,则称这条边为有向边,也成为弧arc,用有序偶对(v1,v2)表示,其中v1表原创 2022-06-23 17:07:19 · 398 阅读 · 0 评论 -
二叉树的基本性质与遍历
二叉树:就是一棵树中每个结点最多只有两个结点,可以没有结点,也可以只有一个结点,也可以为空结点下面说一下二叉树的常见形态: 满二叉树与完全二叉树的区别: 满二叉树就是除了叶子结点之外,每一个结点都有两个孩子 完全二叉树就是每一个结点不一定有两个孩子,但是如果出现在同一层,完全二叉树结点的i位置与满二叉树结点的 i位置编号相同,就是完全二叉树。 所以,满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树然后来说一下二叉树的性质: 1.在原创 2022-06-22 17:41:18 · 437 阅读 · 0 评论 -
顺序栈遍历二叉树
在做这道题之前,需要用到顺序栈,那么还是老规矩,把之前的做的顺序栈做成一个动态库,这样方便使用,不会顺序栈和制作动态库的同学可以去看我另外的文章。先去到存放库的文件夹里面看看,有没有动态库上面很明显有这样的动态库libseqstack.so,因此可以直接来使用先来上一个二叉树:分析一下遍历过程: 下面我们打印像下面这棵树:直接上代码:这里面引入了顺序栈1.0的动态库,可以去看我的文章non_recursion.c 结果:...原创 2022-06-22 16:25:14 · 256 阅读 · 0 评论 -
顺序栈1.0版本
之前做了一个顺序栈和链式栈,这里为什么说把顺序栈升级一下,在于我在写用顺序栈遍历二叉树的时候,出现了一个问题,看看之前我写的顺序栈里面的数据存储这里面存放的是int 类型的元素,但是对于二叉树来说,我们需要遍历出复杂的数据结构类型也就是把这个节点的地址传入到栈里面,所以我们必须修改栈里面的数据类型,以至于可以来存放任何的数据类型话不多说,直接上代码:seqstack1.0.hseqstack1.0.c然后看测试程序main.c运行结果:然后我们把这个顺序栈做成一个动态库 然后把这个库移到原创 2022-06-22 14:59:28 · 307 阅读 · 0 评论 -
数据结构与算法之递归
直接或间接地调用自身的算法称为递归算法。通过这种递推关系把原来问题缩小成一个更小规模的同类问题,并延续这一缩小规模的过程,直到在某一规模上,问题的解是已知的。这样一种解决问题的思想我们称为递归的思想。常见题目1:求n的阶乘 上面的代码是不是就印证了当问题缩小到一定的规模的时候,问题是有解的,像上面这个问题,当n==1的时候,题目就是有解的。下面来说一下递归需要注意的两点:第一,递归必须有递推关系,比如上面这道题的递推关系就是n与n-1的一个递推关系,比如求n的阶乘就是求n*(n-1)!的阶乘第原创 2022-06-16 06:35:14 · 445 阅读 · 0 评论 -
树的基本概念与存储结构
树,大概就是长成下面这个样子,标准定义:n个节点的有限集(n>=0),当n=0的时候,空树,但是在某些时候,n不能等于0换句话说,树是由实根结点与若干子树构成。借助上面的图可以说几个相关概念:根:只有一个,就是A结点,落叶归根嘛子树(SubTree):n>1时,树才会存在子树,子树与子树之间是互不相交的我上面这棵树,那么它的子树就是:如果把内部结点B当成根结点,那么它的子树:如果把内部结点C当成根结点,那么它的子树:度(degr..原创 2022-04-19 16:33:38 · 260 阅读 · 0 评论 -
队列之链式存储
关于队列的描述的常见的操作,在之前的队列之顺序存储里面说过,有不懂的同学可以去看队列之顺序存储这篇文章,这里不在阐述。这里的代码设计,我们需要用到单链表的设计思想,关于单链表的设计不懂的可以去看我另外一篇文章,单链表的设计。这里简单说一下两者区别,直接上图:话不多说,直接上代码:linkqueue.h#ifndef _LINKQUEUE_H_#define _LINKQUEUE_H_//定义数据节点类型typedef int elem_type;//直接定义一个链表结构原创 2022-02-24 16:41:51 · 252 阅读 · 0 评论 -
队列之顺序存储
这个和栈一样,只不过它是先进先出的原则,这东西就像排队一样,先进来的先出去,后进来的后出去话不多说,直接上图:下面说一下队列的实现方式,依旧是用数组或者链表来实现:还是利用了顺序表的设计思想,不懂顺序表的同学,可以去看我的文章顺序表的设计。话不多说,直接上代码:seqqueue.h#ifndef _SEQQUEUE_H_#define _SEQQUEUE_H_#define ARR_MAX_SIZE 100//元素类型typedef int elem_typ.原创 2022-02-22 23:41:22 · 301 阅读 · 0 评论 -
栈之栈的链式存储
之前说了顺序存储,具体分析,请看栈之栈的顺序存储,现在说用链表的操作:顺序存储的时候,我用的是游标top_of_index 来控制top角标,那么在单链表中怎么控制栈顶呢,无非就是一直头插就行了,头插就是在栈顶插入。那么出栈呢,出栈无非就是还是从头操作,因为头是栈顶嘛,我们直接把这个节点销毁(前提是这个节点分配了内存空间)或者指向第一个节点的下一个节点就ok了。另外,关于单链表的插入与删除,请看单链表的设计,另外关于一些常见操作与顺序存储插不多可以查看我另外一篇文章。总之呢,大致设计思想原创 2022-02-11 20:54:10 · 600 阅读 · 0 评论 -
栈之栈的顺序存储
栈(stack):再来说说栈的几个概念与常见操作:栈的设计思路:下面说一下栈的顺序存储原理:具体代码设计思想:话不多说,直接上代码:stack.h:#ifndef _STACK_H_#define _STACK_H_#define EMPTY_INDEX -1 //代表栈里面没有元素#define MAX_SIZE 100 //这里设计可以大一点,防止数据溢出//定义抽象的数据存放类型typedef int element_type;//...原创 2022-02-11 19:03:52 · 787 阅读 · 0 评论 -
顺序表习题之清楚重复元素
Title DescriptionIn the table with length N, n < 1000, there are some duplicate elements. We need to clear these duplicate elementsinputEnter the length of the table in the first row n:The second line successively outputs the stored N element va原创 2021-12-23 21:18:26 · 4076 阅读 · 0 评论 -
链表的合并
我先是设计了一个单链表,完了之后插入数据,啥也不说,直接show codelinklist.h:#ifndef _LINKLIST_H_#define _LINKLIST_H_//数据节点typedef struct _link_list_node link_list_node;struct _link_list_node { int data; link_list_node *next;};//头节点typedef struct _t_link_list{ int原创 2021-12-23 10:21:30 · 357 阅读 · 0 评论 -
双向链表的设计
内存结构分析:插入与删除分析:下面看代码实现:头文件dlinklist.h#ifndef _DLINKLIST_H_#define _DLINKLIST_H_#include <stdio.h>#include <stdlib.h>//数据节点typedef struct _dlink_list_node dlink_list_node;struct _dlink_list_node{ int data; dlink_list_node .原创 2021-12-21 12:52:38 · 306 阅读 · 0 评论 -
循环链表设计
上面内存结构分析,下面数据结构分析:下面插入与删除分析:代码设计:circlelist.h#ifndef _CIRCLELIST_H_#define _CIRCLELIST_H_//数据节点typedef struct _circle_list_node circle_list_node;typedef struct _circle_list_node{ int data; circle_list_node *next;}circle_list_node;...原创 2021-12-20 21:27:21 · 466 阅读 · 0 评论 -
顺序表的设计
思考:上面就是顺序表的内存结构分析:下面看实现:头文件:seqlist.h#ifndef _SEQLIST_H_#define _SEQLIST_H_#define ARR_MAX_SIZE 10//定义数据节点typedef int seq_list_node;//头节点typedef struct _t_seq_list{ int capacity; int length; seq_list_node node[];//本身就是数组存放空间}t_seq..原创 2021-12-18 19:34:35 · 365 阅读 · 0 评论 -
静态链表代码升级
之前静态链表初尝试代码的内存图如下所示:note:上面在来多说一下,之前我把最后一个数据的结尾设置成0,这也是我为什么node[0]这个位置用来存放长度与下一个节点索引的一个重要原因,因为0就代表结尾同时又是数组的第一个下标索引,第二个原因是node[0]可以方便我们在数据插入、删除、寻找的时候进行数据移动。而现在,因为node[0]这个位置我们要存放数据我们这样设计把结尾的索引位置为-2,为什么不能设置成-1,或者其他正数下标,假设如果设置成-1,那么你插入的最后一个元素,它的next就是-1原创 2021-12-18 18:16:17 · 684 阅读 · 0 评论 -
静态链表初尝试
静态链表的设计思想:下面看具体实现代码:首先看头文件:staticlist.h#ifndef _STATICLIST_H_#define _STATICLIST_H_#define MAX_SIZE 10//数据节点typedef struct _static_list_node{ int data; int next;}static_list_node;//头节点typedef struct _t_static_list{ int capacity; sta.原创 2021-12-18 13:33:49 · 452 阅读 · 0 评论 -
单链表的设计
先来写一个头文件:linklist.h#ifndef _LINKLIST_H_#define _LINKLIST_H_//数据节点typedef struct _link_list_node link_list_node;struct _link_list_node { link_list_node *next; int value;};link_list_node* create();int get_len(link_list_node *原创 2021-12-13 19:49:53 · 398 阅读 · 0 评论