数据结构与算法
关于数据结构与算法的个人理解和总结博文,附带C实现源码
mootun
放荡不羁程序员
展开
-
算法_考考你——判断二叉树的子结构(剑指Offer真题)
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)判断B是否是A的子结构递归模型描述递归出口:B为空, 返回trueA为空,返回false如果A 与 B相同–>> 如果B的左子树是A的左子树的子结构–>> 如果B的右子树是A的右子树的子结构, 返回true递归体:判断B是否是A的左子树的子结构判断B是否是A的右子树的子结构/*struct TreeNode { int val; struct TreeN.原创 2020-05-11 09:40:37 · 155 阅读 · 0 评论 -
算法_快速排序的分析+过程描述以及改进方法
快速排序的基本思想是通过一趟排序将原表划分成两个子表,其一一个子表的元素比另一个子表的都要小,然后再对两个子表进行快速排序,直到表中元素有序排列。算法分析与过程描述从定义可以看出,快速排序的过程是递归的,因此,其排序过程可以描述成对应的一棵递归树。以下分析假设待排序的表有n个元素。当元素基本无序的时候,每一趟划分都将原表划分成两个表,并且归位一个元素,这时划分过程可以近似看成一棵完全二叉树,...原创 2020-04-13 12:06:58 · 246 阅读 · 0 评论 -
算法_查找二叉树中结点值为x的结点所在的层次
查找结点值为x的结点所在的层次,考虑的是结点唯一的情况int find_node_level(BTNode *bt, ElemType x, int h){ if (bt == NULL) return 0; else if (bt->data == x) return h; else { int l = f...原创 2020-04-13 08:57:25 · 8753 阅读 · 1 评论 -
算法_统计二叉树第k层的结点个数
统计第k层的结点个数//全局变量版int cnt = 0;void count_node_k(BTNode *bt, int k, int h){ if (bt == NULL) return ; else if (h == k) cnt++; else if (h < k) { count_node_k...原创 2020-04-13 08:49:39 · 2132 阅读 · 0 评论 -
函数指针的应用——参数化排序规则(以冒泡排序为例)
函数是通常被封装成处理数据的功能模块,而函数指针使得函数可以在函数之间高效地进行传递。利用这函数的这个功能和函数指针的特点,可以实现对排序函数的排序规则的参数化。下面是实现思路及代码通常,排序函数的基本功能是实现数据按关键字递增或递减排序,所以可以封装两个功能函数://元素增规则bool less_than(int a, int b){ return (a < b);}...原创 2020-04-12 10:44:37 · 282 阅读 · 0 评论 -
算法_基数排序(思路、C代码实现、算法分析)
思路基数排序的主要思想:借助多关键字进行排序的算法算法的步骤主要是:分配和收集基本思路: 1.先按元素的某位数作为关键字进行分配——关键字相同的放到同一队列2. 然后对元素进行收集——按关键字的顺序对所有分配的元素进行连接3. 对1、2步骤重复元素的位数次,最后收集所得的元素已排好序相关概念分类:LSD最低位优先MSD最高位优先主要操作步骤:分配收集前提...原创 2020-03-28 20:39:21 · 251 阅读 · 0 评论 -
算法_二路归并排序
思路二路归并的基本思想是将元素表看成n个长度为1的有序表,然后对其进行两两归并,再对归并得到的有序表进行两两归并,直到得到一个长度为n的有序表。实现二路归并的过程可以描述成一棵归并二叉树,实现方法有两种//1.自顶向下(递归)void merge_sort(RecType R[], int n){ mergeRC(R, 0, n-1);}void mergeRC(RecT...原创 2020-03-28 17:43:03 · 423 阅读 · 0 评论 -
算法_选择排序之堆排序
什么是堆?堆的概念:所有分支结点都大于(小于)其孩子结点的完全二叉树称为大(小)根堆。因此,大(小)根堆的根结点必定是最大(小)元素。利用简单选择排序的思路,就可以每次从大(小)根堆中选取根结点,使元素序列有序。思路堆排序是一种树形选择排序方法,它的特点是将元素序列看成是一个完全二叉树的顺序存储结构,利用堆的性质对元素进行排序。实现void heap_sort(RceType R[],...原创 2020-03-27 19:31:01 · 537 阅读 · 0 评论 -
算法_选择排序之简单选择排序
思路每趟从无序区里选一个最小的元素放到有序区的后面简单选择的思路://在区间i~n之间选择最小元素int min(int a[], int n, int i){ int k = i, j; for (j=i+1; j<n; j++) if (a[j] < a[k]) k = j; return a[k];}实现void sel...原创 2020-03-27 17:01:35 · 274 阅读 · 0 评论 -
算法_交换排序之快速排序
思路在表中随机选一个元素作为基准,将表划分成两个子表,其中左子表元素小于等于基准,右子表大于等于基准,基准归位。然后对子表再进行划分,直到某个子表的元素小于2。此时表中元素已有序。实现void quick_sort(RceType R[], int s, int t){ int i, pivot; pivot = (s + t) / 2; if (s < t)...原创 2020-03-27 15:28:07 · 114 阅读 · 0 评论 -
算法_交换排序之冒泡排序
思路将元素序列分成有序和无序区。从后往前将元素两两进行比较,如果相对逆序,则交换元素,直到将一个元素合并到有序区的后面。重复以上步骤,直到无序区剩下一个元素。实现void bubble_sort(RecType R[], int n){ int i, j; bool exchange; for (i=0; i<n-1; i++) { e...原创 2020-03-26 20:40:05 · 124 阅读 · 0 评论 -
算法_插入排序之希尔排序
排序思路希尔排序是一种分组插入方法。先取一个小于元素个数n的正整数d,将元素分成d组,依次对每组内部进行直接插入排序,完成一趟后,再取一个小于d的增量,重复以上步骤,直到增量为1时进行最后一趟排序,此时元素基本正序。实现void shell_sort(RecType R[], int n){ int i, j, d; RecType tmp; d = n/2; ...原创 2020-03-26 19:42:54 · 141 阅读 · 0 评论 -
算法_插入排序之直接插入排序
插入排序的基本思路就是将所有元素划分为两个区间:有序区和无序区,开始时有序区只有一个元素,然后依次将无序区的元素一个一个地插入到有序区当中,这种方法称为增量法,每插入一个元素称为一趟插入。直接插入排序的基本思路从后向前在有序区中顺序查找插入位置,边查找边移动,当找到第一个小于插入元素的元素,就在它后面插入。算法void insert_sort(RecType R[], int n){ ...原创 2020-03-26 17:32:29 · 222 阅读 · 0 评论 -
算法_插入排序之折半插入排序
基本思想考虑到直接插入排序的基本思想就是每次将无序区里的元素插入到有序区,那么可以利用表的有序性在有序区中使用折半查找查找插入位置。对于递增有序表,我们查找插入位置就是第一个关键字大于插入元素关键字的元素位置,因此折半插入就需要查找有序区中第一个关键字大于要插入元素关键字的元素位置。综合以上分析 ,可以采用与直接插入排序相同的方法,扫描无序曲,依次比较元素,然后元素插入的位置使用折半查找,然...原创 2020-03-26 16:17:51 · 263 阅读 · 0 评论 -
算法_二叉排序树(BST)总结及其删除操作实现细节剖析
二叉排序树的总结定义二叉排序树:或者是一棵空树,或者是一棵满足BST性质的二叉树。BST性质:1)如果根结点有左子树,则左子树的所有结点的关键字值都小于根结点的;2)如果根结点有右子树,则右子树的所有结点的关键字值都大于根结点的;3)左、右子树都是二叉排序树。注意可能有人会问,为什么通常称BST为二叉排序树而不是二叉搜索树?原因是:BST的创建过程的本质是对元素序列的排序。...原创 2020-03-23 18:51:52 · 420 阅读 · 0 评论 -
算法_Prim算法构造最小生成树
基本概念:生成树:一个连通图的生成树是它的一个极小连通子图从生成树的定义可知,一个连通图的生成树含有图的全部n个顶点和n-1条边。最小生成树(minimal spanning tree):给连通图的边附上权值,则其所有权值之和最小的生成树是最小生成树。Prim算法构造最小生成树:假设有连通图G=(V,E),其最小生成树表示为G’=(U,TE)。从V中选择一个顶点v作为起点加入到U中,...原创 2020-03-22 15:43:17 · 642 阅读 · 0 评论 -
算法_二叉树的非递归中序遍历(C/C++实现)
中序非递归遍历:思路:左子树 、 根 、 右子树辅助数据结构:栈算法分两步:从根结点开始找到最左下结点(边找边进栈),此时最左下结点的左孩子为NULL,即可认为最左下结点的左子树已被访问过,此时最左下结点可以看做是有一棵空左子树的根结点。如果栈不空,出栈(算法最开始的时候访问的是第一步找到的最左下结点),访问结点,此时可认为以栈顶结点作为根的子树的根结点已被访问,然后对出栈结点的右孩子...原创 2020-03-20 08:43:01 · 377 阅读 · 0 评论 -
算法_二叉树的非递归后序遍历(C/C++实现)
二叉树的非递归后序遍历:前中后序三种遍历的非递归实现,都是使用了栈的思想,而后序遍历是其中最复杂的一种,因此只要掌握了它就很容易理解其他两种。下面给出思路和代码实现后序遍历:思想:左子树、右子树、根因此算法分两步:找到最左下结点,其左孩子为NULL,此时可以认为最左下结点的左子树已被访问 --> 统一最左下结点和其他根结点的情况判断栈顶结点的右子树是否已被访问,因为对于任...原创 2020-03-17 11:41:08 · 1057 阅读 · 0 评论 -
算法_根据哈夫曼树创建哈夫曼编码(C/C++)
文章结构:基本思路 + 代码实现基本思路:在根结点到叶子结点的路径上,从叶子结点开始依次逆向判断每个结点是左还是右孩子,根据判断结果将编码存储到数组中,直到当前结点没有双亲结点——即根结点。代码实现:1)哈夫曼编码类型声明:typedef struct{ int code[MaxSize]; int start;}HFCode;2)实现算法:void creat...原创 2020-03-05 18:06:00 · 555 阅读 · 0 评论 -
算法_二叉树的层序遍历算法(C/C++)
本文结构:基本思路 + 实现代码基本思路:层序遍历的定义是从根结点开始,按照从上到下,从左到右的顺序访问二叉树的每个结点。那么具体到某个结点——根结点与它的左、右孩子,根A->左孩子B->右孩子C,下一遍是结点B->左孩子->右孩子->结点C->左孩子->右孩子,以此类推直到访问完全部结点,其过程具有“先进先出”的特点,因此用队列辅助算法的实现。...原创 2020-03-05 17:41:11 · 276 阅读 · 0 评论 -
数据结构_哈夫曼树定义、构造方法及实现(C/C++)
基本概念:结点带权路径长度(Weight Path Length,WPL):结点权值 x 根结点到结点自身的路径长度树的带权路径长度:所有叶子结点WLP之和Huffman树/最小二叉树的定义:n个结点所构造出的WPL最小的二叉树哈夫曼树的构建:给定n个带权结点,将n个结点构成n棵二叉树的森林,每棵二叉树仅有一个根结点,没有左右子树。从n个结点中选出两个根结点权值最小的树分别作为左右...原创 2020-03-02 22:45:33 · 954 阅读 · 0 评论 -
数据结构_队列:从普通队列到循环(circular)队列
队列:从普通队列到循环队列队列的定义:队列(queue)是允许在一端进行插入操作,在另一端进行删除操作的线性表。允许插入的一端称为队尾(rear),允许删除的一端称为队头(front)。插入操作称为入队或进队(enqueue),删除操作称为出队或离队(dequeue)。队列的主要特点是“先进先出”,因此也称为先进先出表。如:在饭堂某个窗口排队打饭的若干个同学,就可以看成是一个队列。实现...原创 2020-03-02 19:23:04 · 287 阅读 · 0 评论 -
算法_二叉树的前、中序线索化及输出(C/C++实现)
二叉树的前序线索化背景:以二叉链实现的二叉树中,存储空间的利用效率较低。假设有一棵有n个结点的二叉链实现的二叉树,则其公有2n个指针域,而其中只有n-1个分支结点(除了1个根结点以外,其他都是分支结点),因为每个分支结点都有一个指针域对应,因此有:2n - (n-1) = n+1个指针域空置,为了提高存储空间的利用率并且提高二叉树遍历的速度,因此需要对二叉树进行线索化,创建线索二叉树。相对于二...原创 2020-03-02 11:20:54 · 389 阅读 · 0 评论 -
算法_前序遍历二叉树的非递归实现(C/C++)
为了加深对二叉树遍历思想的理解,以及锻炼分析和解决问题的能力,以下对前序遍历二叉树的非递归实现算法进行分析、实现及总结。分析:给定任意一棵二叉树,对其进行前序遍历,即先访问根结点,然后访问左其孩子,再访问其右孩子。但是用二叉链实现的二叉树其结点的本质是具有两个指针域的单向链表的结点,既然是单链表结点,就意味着直接向前访问了某个结点后,将无法访问这个结点的兄弟结点,因此需要考虑将要访问某个孩子结点...原创 2020-02-29 19:56:49 · 763 阅读 · 0 评论 -
算法_栈(stack)的应用——判断表达式的括号是否对称
栈(stack)的应用——判断表达式的括号是否对称1. 问题描述:假设有一个使用了圆括号的算术表达式,设计一个算法判断其中的圆括号是否配对。2. 问题分析:首先要理解什么是配对,配对的情况是表达式中左括号的数量与右括号的数量相同,然而如何让括号配对起来呢?只要出现一个左括号那么后面就要出现一个右括号,这样可以完成配对,但是表达式当中某个括号对里面可能还有其他括号对,而且考虑到括号的一个特点...原创 2020-02-28 15:00:56 · 871 阅读 · 0 评论 -
算法_二叉树递归算法(C/C++实现)总结
二叉树递归算法(C实现)总结前言:遍历是数据结构中的一种基本且重要的算法,许多算法都是基于遍历之上实现的。相对于线性表,树是一种非线性结构,不能单纯地利用循环思想进行遍历,而是递归的思想,因为树是一种递归的数据结构(树的定义是递归的)。以下对二叉树的递归遍历算法以及基于递归遍历实现的其他算法进行总结。实现的算法有:遍历输出判断相似输出所有叶子结点求结点总数求结点值为x的结点所在...原创 2020-02-27 17:02:30 · 1117 阅读 · 0 评论 -
数据结构_二叉树(binary tree)基本定义、性质、理解总结+代码实现(C/C++)
二叉树(binary tree)基本定义、性质、理解、总结+代码实现约定:层序编号:二叉树从根结点开始按照从上到下,从左到右的顺序从1开始给结点编号。二叉树(binary tree)定义:一个有限的结点集合。这个集合或者为空,或者由一个根结点和两棵互不相交的称为左子树(subtree)和右子树的二叉树组成。二叉树是一种特殊的树形数据结构,二叉树的定义也是递归的,这决定了对二叉树的算法设计...原创 2020-02-27 12:52:32 · 2344 阅读 · 0 评论 -
数据结构_抽象数据类型(ADT)
抽象数据类型1.定义抽象数据类型(abstract data structure,ADT)是用户进行软件系统设计时从问题的数学模型中抽象出来的逻辑数据结构和逻辑数据结构的运算,而不考虑计算机的存储结构和运算的具体实现算法。2.描述方法用三元组描述。格式如下:ADT(D,R,P),其中{D:数据对象的声明R:数据关系的声明P:基本运算的声明}3.实现最终将ADT的逻辑结构实现...原创 2020-02-18 17:54:06 · 905 阅读 · 0 评论 -
数据结构_逻辑结构
逻辑结构作为数据结构的一部分,这里记录两种常用的描述方法。 1. 图表法 2. 二元组1. 图表法:即用图形或表格的形式描述数据的逻辑关系。2. 二元组:二指的是数据集(D表示)和关系集(R表示) 格式:B(D,R),其中: { D = {ai | 1<= i...原创 2020-02-18 17:35:43 · 719 阅读 · 0 评论 -
数据结构_重要概念总结和理解
背景:数据结构重要性体现在两个方面:1. 作为深入计算机科学的核心基础,操作系统、编译原理、数据库原理等技术的学习与数据结构密切关联。2. 随着计算机的应用领域不断扩大,非数值计算问题占据了计算机应用的大多数,简单的数据类型已经不能满足需要。要理解数据结构,首先要明白什么是数据结构。定义: 数据结构是指数据元素和元素之间的关系,也可看成相互之间存在着某种特定关系的数据元素的集...原创 2020-02-18 17:28:38 · 339 阅读 · 0 评论