数据结构
李歘歘
某不知名学院毕业生、非知名厂打工人
展开
-
数组的顺序表示和实现
线性表的顺序表示和实现可以适当的先了解一下stdarg头文件写的三个宏:va_start、va_arg、va_end。#include<cstdio>#include<cstdlib> #include<cstdarg> //标准头文件,提供三个宏(va_start、va_arg和va_end) //用于存取变长参数表#define E...原创 2020-03-07 18:24:33 · 1826 阅读 · 0 评论 -
稀疏矩阵
#include<cstdio>#include<cstring>#define ElemType int #define Status int //稀疏矩阵的三元组顺序表存储表示 #define MAXSIZE 12500 //非零元的最大个数#define MAXRC 100 //非零元的最大个数typedef struct{ ...原创 2020-03-17 22:44:14 · 958 阅读 · 0 评论 -
拓扑排序
如果一个有向图的任意顶点都无法通过一些有向边回到自身,那么称这个有向图为有向无环图(Directed Acyclic Graph,DAG)。拓扑排序是将有向无环图G的所有顶点排成一个线性序列,使得对图G中的任意两个顶点u、v,如果存在边u->v,那么在序列中uー定在v前面。这个序列又被称为拓扑序列。具体做法可以抽象为:①定义一个队列Q,并把所有入度为0的结点加入队列。②取队首...原创 2020-02-20 12:09:09 · 433 阅读 · 0 评论 -
kruskal算法
kruskal算法(读者可以将其读作“克鲁斯卡尔算法”)同样是解决最小生成树问题的一个算法。和prim算法不同,kruskal算法采用了边贪心的策略,其思想极其简洁,理解难度比prim算法要低很多。kruskal算法的基本思想为:在初始状态时隐去图中的所有边,这样图中每个顶点都自成一个连通块。之后执行下面的步骤:①对所有边按边权从小到大进行排序。②按边权从小到大测试所有边,如果当前...原创 2020-02-18 12:09:07 · 4077 阅读 · 3 评论 -
最小生成树——prim算法
最小生成树(Minimum Spanning Tree,MST)是在一个给定的无向图G(V,E)中求一棵树T,使得这棵树拥有图G中的所有顶点,且所有边都是来自图G中的边,并且满足整棵树的边权之和最小。下图给出了一个图G及其最小生成树T,其中较粗的线即为最小生成树的边。可以看到,边AB、BC、BD包含了图G的所有顶点,且由它们生成的树的边权之和为6,是所有生成树中权值最小的。最小生成树有3...原创 2020-02-15 10:59:53 · 13155 阅读 · 1 评论 -
Floyd算法
最短路径是图论中一个很经典的问题:给定图G(V,E),求一条从起点到终点的路径,使得这条路径上经过的所有边的边权之和最小。对任意给出的图G(V,E)和起点S、终点T,如何求从S到T的最短路径。解决最短路径问题的常用算法有Dijkstra算法、Bellman-Ford算法、SPEA算法和Floyd算法。Floyd算法(读者可以将其读作“弗洛伊德算法”)用来解决全源最短路问题,即对给定的...原创 2020-02-14 15:54:17 · 1064 阅读 · 0 评论 -
Bellman--Ford算法和SPFA算法
最短路径是图论中一个很经典的问题:给定图G(V,E),求一条从起点到终点的路径,使得这条路径上经过的所有边的边权之和最小。对任意给出的图G(V,E)和起点S、终点T,如何求从S到T的最短路径。解决最短路径问题的常用算法有Dijkstra算法、Bellman-Ford算法、SPEA算法和Floyd算法。Dijkstra算法可以很好地解决无负权图的最短路径问题,但如果出现了负权边,Dijk...原创 2020-02-14 13:32:21 · 1222 阅读 · 0 评论 -
图的遍历
图的遍历是指对图的所有顶点按一定顺序进行访问,遍历方法一般有两种:深度优先搜索(DFS)和广度优先搜索(BFS)。关于DFS和BFS以及在树中的应用请参考从树的遍历看DFS和BFS深度优先搜索(DFS)广度优先搜索(BFS)下面把它们应用于图的遍历中。1.深度优先搜索(DFS)深度优先搜索以“深度”作为第一关键词,每次都是沿着路径到不能在前进时才退回到最近的岔道口。...原创 2020-02-11 16:09:27 · 1037 阅读 · 0 评论 -
图的定义和存储
1.图的定义图,顾名思义就是地图一样的东西。抽象出来看,图由顶点(Vertex)和边(Edge)组成,每条边的两端都必须是图的两个顶点(可以是相同的顶点)。而记号G(V,E)表示图G的顶点集为V、边集为E。图一般来说,图可分为有向图和无向图。有向图的所有边都有方向,即确定了顶点到顶点的一个指向;而无向图的所有边都是双向的,即无向边所连接的两个顶点可以互相到达。在一些问题中,可以把无向图当作...原创 2020-02-10 17:01:58 · 893 阅读 · 0 评论 -
哈夫曼树和哈夫曼编码
1.哈夫曼树叶子结点的路径长度是指从根结点出发到达该结点所经过的边数。把叶子结点的权值乘以其路径长度的结果称为这个叶子结点的带权路径长度。另外,树的带权路径长度( Weighted PathLength of Tree,WPL)等于它所有叶子结点的带权路径长度之和。已知n个数,寻找一棵树,使得树的所有叶子结点的权值恰好为这n个数,并且使得这棵树的带权路径长度最小。带权路径长度最小的...原创 2020-02-07 23:25:34 · 2613 阅读 · 0 评论 -
堆及堆排序
1.堆的定义和基本操作堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子结点的值。其中,如果父亲结点的值大于或等于孩子结点的值,那么称这样的堆为大顶堆,这时每个结点的值都是以它为根结点的子树的最大值;如果父亲结点的值小于或等于孩子结点的值,那么称这样的堆为小顶堆,这时每个结点的值都是以它为根结点的子树的最小值。堆一般用于优先队列的实现,而优先队列默认情况下使用的是大顶堆,因此本...原创 2020-02-06 15:39:37 · 797 阅读 · 0 评论 -
并查集
1.定义并查集是一种维护集合的数据结构,它的名字中“并”、“査”、“集”分别取自Union(合并)、Find(査找)、Set(集合)这3个单词。也就是说,并查集支持下面两个操作:①合并:合并两个集合。②査找:判断两个元素是否在一个集合。那么并査集是用什么实现的呢?其实就是用一个数组:int father[N];其中fahter[i]表示元素i的父亲结点,而父亲结点本身也是...原创 2020-02-05 17:57:19 · 1329 阅读 · 0 评论 -
平衡二叉树(AVL)
1.定义平衡二叉树使树的高度在每次插入元素后仍然能保持O(logn)的级别,这样能让查询操作仍然是O(logn)的时间复杂度。平衡二叉树由前苏联两位数学家GM.Adele-Velskil和E.M.Landis提出,因此一般也称作AVL树。AVL树仍然是一棵二叉査找树,只是在其基础上增加了“平衡”的要求。所谓平衡是指,对AVL树的任意结点来说,其左子树与右子树的高度之差的绝对值不超过1,其中...原创 2020-02-04 12:31:45 · 1300 阅读 · 0 评论 -
二叉查找树(BST)
1.定义二叉查找树( Binary Search Tree,BST)是一种特殊的二叉树,又称为排序二叉树、二叉搜索树、二叉排序树。二叉査找树的递归定义如下:①要么二叉査找树是一棵空树。②要么二叉查找树由根结点、左子树、右子树组成,其中左子树和右子树都是二叉查找树,且左子树上所有结点的数据域均小于或等于根结点的数据域,右子树上所有结点的数据域均大于根结点的数据域。从二叉査找树的定义中...原创 2020-02-04 00:01:15 · 1074 阅读 · 0 评论 -
从树的遍历看DFS和BFS
1.深度优先搜索(DFS)和树的先根遍历事实上,对所有合法的DFS求解过程,都可以把它画成树的形式,此时死胡同等价于树中的叶子结点,而岔道口等价于树中的非叶子结点,并且对这棵树的DFS遍历过程就是树的先根遍历的过程。于是可以从中得到启发:碰到一些可以用DFS做的题目,不妨把一些状态作为树的结点,然后问题就会转换为直观的对树进行先根遍历的问题。如果想要得到树的某些信息,也可以借用DFS以深度作为...原创 2020-02-03 11:55:58 · 984 阅读 · 0 评论 -
树的遍历
1.树的先根遍历对一棵一般意义的树来说,总是先访问根结点,再去访问所有子树。显然,这是一个递归访问的概念,因为对根结点的子树来说,同样可以分为根结点和若干子树。这种遍历方式被称为树的先根遍历。代码如下:void PreOrder(int root){ printf("%d ",Node[root].data); //访问当前结点 for(int i=0;i<Node[root...原创 2019-10-21 21:51:03 · 1351 阅读 · 0 评论 -
树的静态写法
我们令指针域存放其所有子结点的地址(或者为其开一个数组,存放所有子结点的地址)。不过这听起来有点麻烦,所以还是建议在考试中使用其静态写法,也就是用数组下标来代替所谓的地址。当然这需要事先开一个大小不低于结点上限个数的结点数组,因此结构体node的定义会类似于下面这样:struct node{ typename data; //数据域 int child[maxn]; //指针域,存放所有...原创 2019-10-16 21:28:11 · 2310 阅读 · 2 评论 -
二叉树的静态实现
不懂树与二叉树的可以参考:树与二叉树通过下面的学习,读者应能完全不使用指针,而简单使用数组来完成二叉树的所有操作。在定义二叉树时,采用的是二叉链表的结构,如下所示:struct node{ typename data; //数据域 node* lchild; //指向左子树根结点的指针 node* rchild; //指向右子树根结点的指针 };在这个定义中,为了能够...原创 2019-10-14 19:48:51 · 1343 阅读 · 0 评论 -
二叉树的遍历——层次遍历
上一节:二叉树的遍历——先序遍历、中序遍历、后序遍历层序遍历是指按层次的顺序从根结点向下逐层进行遍历,且对同一层的结点为从左到右遍历。需要从根结点开始从上往下逐层遍历,而对同一层进行从左到右的遍历。这个过程和BFS很像,因为BFS进行搜索总是以广度作为第一关键词,而对应到二叉树中广度又恰好体现在层次上,因此层次遍历就相当于是对二叉树从根结点开始的广度优先搜索,基本思路如下:①将根结点ro...原创 2019-10-13 20:43:29 · 3558 阅读 · 0 评论 -
二叉树的遍历——先序遍历、中序遍历、后序遍历
二叉树的遍历是指通过一定顺序访问二叉树的所有结点。遍历方法一般有四种:先序遍历、中序遍历、后序遍历及层次遍历,其中,前三种一般使用深度优先搜索(DFS)实现。无论是这三种遍历中的哪一种,左子树一定先于右子树遍历,且所谓的“先中后”都是指根结点root在遍历中的位置,因此先序遍历的访问顺序是根结点→左子树→右子树,中序遍历的访问顺序是左子树→根结点→右子树,后序遍历的访问顺序是左子树→右子树→根...原创 2019-10-13 20:09:06 · 3470 阅读 · 0 评论 -
树与二叉树
1.树的定义与性质(1)树(tree)的概念在数据结构中,树则是用来概括传递关系的一种数据结构。为了简化,数据结构中把树枝分叉处、树叶、树根抽象为结点(node),其中树根抽象为根结点(root),且对一棵树来说最多存在一个根结点;把树叶概括为叶子结点(leaf),且叶子结点不再延伸出新的结点;把茎干和树枝统一抽象为边(edge),且一条边只用来连接两个结点(一个端点一个)。这样,树就被定...原创 2019-10-10 20:15:32 · 1498 阅读 · 0 评论 -
迷宫
给定一个n*m大小的迷宫,其中*代表不可通过的墙壁,而“.”代表平地,S表示起点,T代表终点。移动过程中,如果当前位置是(x,y)(下标从0开始),且每次只能前往上下左右、(x,y+1)、(x,y-1)、(x-1,y)、(x+1,y)四个位置的平地,求从起点S到达终点T的最少步数。......*.*..*S*..***....T*上面样例S为(2,2),T的坐标为(4,3)。...原创 2019-09-27 11:24:20 · 1548 阅读 · 0 评论 -
广度优先搜索(BFS)
广度优先搜索(Breadth First Search , BFS)遍历类似于树的按层次遍历的过程,则是以广度为第一关键词,当碰到岔道口时,总是先依次访问从该岔道口能直接到达的所有结点,然后再按这些结点被访问的顺序去依次访问它们能直接到达的所有结点,以此类推,直到所有结点都被访问为止。广度优先搜索的整个算法过程很像一个队列,因此,广度优先搜索(Breadth First Search , BF...原创 2019-09-24 13:14:58 · 1812 阅读 · 0 评论 -
深度优先搜索(DFS)
深度优先搜索遍历类似于树的先根遍历,是树的先根遍历的推广,在算法竞赛和考试中经常用到,在优化图算法时,也非常方便,就像是在走迷宫过程中,当碰到岔路口时“深度”作为前进的关键词,不碰到死胡同就不回头,因此把这种搜索的方式称为深度优先搜索(Depth First Search, DFS)。深度优先搜索会走遍所有路径,并且每次走到死胡同就代表一条完整路径的形成。这就是说,深度优先搜索是一种枚举所有完...原创 2019-09-22 16:06:40 · 6346 阅读 · 1 评论 -
Link List Sorting
题目描述:A linked list consists of a series of structures, which are not necessarily adjacent in memory.We assume that each structure contains an integer key and a Next pointer to the next structure. No...原创 2019-09-21 15:14:33 · 1239 阅读 · 0 评论 -
Sharing
题目描述:To store English words, one method is to use linked lists and store a word letter by letter. To save some space, we may let the words share the same sublist if they share the same suffix. For e...原创 2019-09-21 10:38:06 · 1502 阅读 · 0 评论 -
静态链表
一般我们使用的链表是动态链表:动态链表但若结点的地址是比较小的整数(例如5位数的地址),这样就没有必要去建立动态链接,而应该使用更方便的静态链表。静态链表的实现原理是hash,即通过建立一个结构体数组,并令数组的下标直接表示节点的地址,来达到直接访问数组中的元素就能达到访问结点的效果。另外,由于结点的访问非常方便,因此静态链表是不需要头结点的。静态链表结点定义的方法如下:st...原创 2019-09-20 18:43:54 · 1672 阅读 · 1 评论 -
链表的基本操作
链表的基本概念以及分配内存空间1.创建链表把每个结点的next指针指向下一个结点的地址即可。程序代码:#include<cstdio> //#include<stdlib>struct node { int data; //数据域 node* next; // 指针域 };//创建链表node* create(int Array[...原创 2019-09-20 12:08:35 · 5736 阅读 · 2 评论 -
链表
1.链表的概念线性表是一类很常用的数据结构,分为顺序表和链表。其中顺序表可以简单地理解成前面介绍的“数组”这个概念,而这里将要讲解一下链表。按正常方式定义一个数组时,计算机会从内存中取出一块连续的地址来存放给定长度的数组;而链表则使由若干个结点组成(每个结点代表一个元素),且结点在内存中的存储位置通常是不连续的。除此之外,链表的两个结点之间一般通过一个指针来从一个结点指向另ー个结点,因此链表的...原创 2019-09-18 11:48:01 · 1823 阅读 · 0 评论 -
队列的应用
队列(queue)是一种先进先出的数据结构,总是从队尾加入元素,而从队首移除元素。使用一个队首指针front来指向队首元素的前一个位置,而使用一个队尾指针rear来指向队尾元素,当使用数组来实现队列时,队首元素front和队尾元素rear为int型变量(数组下标从零开始);而当使用链表来实现队列时,则为int* 型变量的指针。接下来介绍队列的常用操作,包括清空( clear)、获取队列内元素的...原创 2019-09-17 13:43:32 · 1474 阅读 · 0 评论 -
栈的应用
栈(stack)是一种先进后出的数据结构(又称为后进先出的线性表),每次只能使用栈顶指针对栈顶元素进行操作(进栈出栈),栈顶指针是始终指向栈的最上方的元素的一个标记。当使用数组实现栈时,栈顶指针是一个int型的变量(数组下标从0 开始),通常即为TOP; 而当使用链表实现栈时,则为int*型的指针。当栈中没有元素时令TOP为-1,即空栈。使用stack需要在头文件中加入“#include<...原创 2019-09-17 10:50:57 · 1465 阅读 · 0 评论