数据结构与算法
萧-十一
这个作者很懒,什么都没留下…
展开
-
【数据结构】栈的数组实现
1.栈的顺序存储实现 构建结构体Stack,其中数组Date存放栈中数据,Top存放栈顶元素的下标。对栈进行初始化时将Top赋值为-1,表示栈为空。MaxSize为栈的最大容量。#define MaxSize 10typedef struct Stack{ int Date[MaxSize]; int Top;} Stack;2.进栈操作 进栈操作前应当先检查栈是否已满,避免原创 2017-03-08 19:55:16 · 656 阅读 · 0 评论 -
【算法】快速排序
void QuikSort(int *a, int left, int right){ if(left < right){ int key = a[left]; int low = left; int high = right; while(low < high){ while(low < high &原创 2017-12-03 21:01:32 · 157 阅读 · 0 评论 -
【算法】归并排序
基本思想将待排序数组a[n]看做n个长度为1的有序序列,然后将每两个相邻的有序序列归并为一个新的有序序列,重复这个过程直到整个数组有序,这就是归并排序的基本思想。 所以我们可以将归并排序的过程分为两步:分解:按照确定的长度对数组进行划分归并: 对划分好的各个部分进行两两归并时间复杂度可以想象归并排序的过程类似一个二叉树的形成过程,所以易得时间复杂度为O(nlgn)空间复杂度由于在归并时使用了原创 2017-12-04 20:52:37 · 160 阅读 · 0 评论 -
【数据结构】筛选法建堆
如果已经存在N个数据元素,如何将这些元素按照堆的要求存储在一个一维数组中呢?这就是堆的建立问题。 首先我们可以想到按照之前的堆的插入算法将这N个元素依次插入一个空堆中,分析时间复杂度,每插入一个元素最多要进行logN(即堆的深度)次比较,所以对于N个元素用插入法建堆的时间复杂度是O(NlogN)。 这里要介绍的是筛选法建堆,它可以在线性时间复杂度下完成建堆。以最大堆为例介绍具体操作过程:首先将原创 2017-05-29 16:06:35 · 57080 阅读 · 5 评论 -
【算法】堆排序
堆排序是建立在堆这种数据结构上的一种排序算法,是选择排序的一种。 堆排序的思想是:利用最大堆(或最小堆)输出堆顶元素,即最大值(或最小值),再将剩下的元素重新生成最大堆(或最小堆),继续输出堆顶元素,重复此过程,直到全部元素都被输出,得到的输出序列就是有序序列。 很显然,堆排序算法的实现只需要借助之前的博文中提到的堆的建立和删除算法即可完成。 我们可以新建一个数组用于存放输出序列,不过这样太过原创 2017-06-02 22:59:08 · 428 阅读 · 0 评论 -
【lintcode】两数之和、三数之和、最接近的三数之和、四数之和小结
两数之和给一个整数数组,找到两个数使得他们的和等于一个给定的数 target。你需要实现的函数twoSum需要返回这两个数的下标, 并且第一个下标小于第二个下标。注意这里下标的范围是 1 到 n,不是以 0 开头。你可以假设只有一组答案。样例给出 numbers = [2, 7, 11, 15], target = 9, 返回 [1, 2].思路: 我们想到的最简单的方法是使用两个for循环原创 2017-11-20 20:14:16 · 1616 阅读 · 2 评论 -
【lintcode】最大子数组
题目描述:给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。子数组最少包含一个数样例给出数组[−2,2,−3,4,−1,2,1,−5,3],符合要求的子数组为[4,−1,2,1],其最大和为6解法一:分治法 O(nlgn)我们将一个数组分为两部分,关于它的最大子数组存在如下三种情况: 1.最大子数组属于第一部分 2.属于第二部分 3.横跨两个部分 所以我们只需将这三个可能的值求出原创 2017-12-19 14:22:49 · 484 阅读 · 0 评论 -
【lintcode】LRU缓存策略
为最近最少使用(LRU)缓存策略设计一个数据结构,它应该支持以下操作:获取数据(get)和写入数据(set)。获取数据get(key):如果缓存中存在key,则获取其数据值(通常是正数),否则返回-1。写入数据set(key, value):如果key还没有在缓存中,则写入其数据值。当缓存达到上限,它应该在写入新数据之前删除最近最少使用的数据用来腾出空闲位置。 思路: 使用如上图所示原创 2018-01-18 13:11:47 · 353 阅读 · 0 评论 -
【算法】并查集—带路径压缩的按秩合并法
读了《算法导论》的21章:用于不相交集合的数据结构 后在这里对并查集算法做一个小结。 对于动态集合的表示有多种方法,例如链表和有根树。不论是哪种表示,我们都用一个代表来标识一个集合,这个代表就是该集合中的某个成员。 并查集算法用于对不相交集合的查找与合并,主要是以下三种操作:MAKE_SET(X):创建一个新的集合,它包含唯一的成员x(因而为代表)。UNION(x,y):将分别包含x和...原创 2018-02-04 21:04:41 · 6231 阅读 · 2 评论 -
【lintcode】图是否是树
给出 n 个节点,标号分别从 0 到 n - 1 并且给出一个 无向 边的列表 (给出每条边的两个顶点), 写一个函数去判断这张`无向`图是否是一棵树注意事项你可以假设我们不会给出重复的边在边的列表当中. 无向边 [0, 1] 和 [1, 0] 是同一条边, 因此他们不会同时出现在我们给你的边的列表当中。样例给出n = 5 并且 edges = [[0, 1], [0, 2], [0,原创 2018-02-04 21:35:52 · 473 阅读 · 0 评论 -
【lintcode】N皇后问题
n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击。给定一个整数n,返回所有不同的n皇后问题的解决方案。每个解决方案包含一个明确的n皇后放置布局,其中“Q”和“.”分别表示一个女王和一个空位置。样例对于4皇后问题存在两种解决的方案:[".Q..", // Solution 1 "...Q", "Q...", "..Q."], ["..Q.", //原创 2018-01-21 00:06:01 · 368 阅读 · 0 评论 -
top k 问题的几种解决方法
top k问题是指给定一组数量为n的数,从中找出前k大的数或第k大的数(k <= n)。由于只要能找出前k大的数,即可以得到第k大的数。所以下面先介绍解决前k大数问题的几种思路:1.部分排序由于我们只需要找到数组nums的前k大的数,所以不需要对整个数据进行排序,只需要保持前k大的数有序即可。所以我们可以维护一个大小为k的数组tk:首先将数组nums的前k个元素放入数组tk...原创 2018-02-22 17:30:53 · 3010 阅读 · 1 评论 -
【算法】单链表的快速排序和归并排序
当我们要对一个单链表进行排序,并要求复杂度为O(nlgn)时。在对数组排序的算法中,复杂度为O(nlgn)的算法有:快速排序、归并排序和堆排序。由于堆排序需要将数据组织成一个最大堆,这对于链表来说需要将其重新构造为一个二叉树,这样做太过复杂并且浪费额外的空间。所以只能考虑快速排序和归并排序。 由于单链表不支持对结点的随机访问,所以不能直接套用在数组上的排序算法。由于快速排序和归并排序都包含二分的...原创 2018-01-30 12:31:10 · 445 阅读 · 0 评论 -
背包问题—01背包、完全背包
01背包问题题目有m件物品和一个容量为V 的背包。放入第i 件物品占用的体积是Vi,得到的价值是Wi。求解将哪些物品装入背包可使价值总和最大。思路这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。所以对于第i件物品,可以转化成与前i-1个物品相关的两个子问题:如果放入第i个物品,那么当前最大的价值f(i,V)就等于将前i-1个物品放入容量为(V-Vi)的背包中...原创 2018-03-09 21:28:08 · 326 阅读 · 0 评论 -
【lintcode】子集问题
这里的子集问题是指给定一个列表求它的所有不重复子集的问题。这个问题分为两类:一类是所给列表包含重复元素,另一类是所给列表不含重复元素。分别对应lintcode中17和18题。1.列表不含重复元素的子集这里使用深度优先搜索的思想,递归求解。 代码class Solution {public: /** * @param nums: A set of numbers...原创 2018-05-24 10:50:17 · 366 阅读 · 0 评论 -
【算法】字符串大整数相乘
题目描述: 给定两个以字符串形式存储的大整数,要求以字符串形式输出相乘后的结果。 思路: 模拟计算乘法时列竖式的过程,对于两个字符串s1和s2,让s2的每一位和s1整体相乘,求得一组中间值,然后对中间值做移位操作,最后将移位后的所有中间值相加即可求得最终结果。 问题的关键在于实现两个函数,用于计算两个字符串相加以及字符串和单个字符相乘的结果。//计算两个字符串相加string mya...原创 2018-07-09 00:35:27 · 1597 阅读 · 0 评论 -
【算法】桶排序和基数排序
桶排序假设我们要对n个整数排序,而且这n个数的大小在区间[0,m]之内。那么我们可以设置m+1个”桶”来表示区间内的m+1个数,用数组bucket[m+1]表示。然后遍历n个待排数据,将每个数字放入到它对应的”桶”中。最后我们按照”桶号”递增的顺序将n个数字一次从”桶”中取出,那么取出的数字序列就是排序后的序列了。 桶排序使用了hash的思想,将n个数散列在了m个”桶”中,然后利用桶固有的顺...原创 2018-07-06 13:37:26 · 405 阅读 · 0 评论 -
【数据结构】红黑树小结
红黑树是一种二叉搜索树。性质一颗红黑树满足以下五个红黑性质:每个结点或者是红色或者是黑色。根结点是黑色的。每个叶结点是黑色的。(这个叶节点是树尾端的黑色节点nil)若一个结点是红色的,它的两个子结点必须是黑色的。对于任意一个结点,从该结点到它的每一个后代叶结点的简单路径上,都包含相同数目的黑色结点。一棵有n个内部结点的红黑树,它的高度至多为2lg(n+1)。也就是说,在一棵...原创 2018-07-14 16:14:59 · 308 阅读 · 0 评论 -
【算法】简单插入排序与希尔排序
简单插入排序简单插入排序的思想非常简单:就是将待排序列分为已经排好的和未排序的两个序列,初始时已排序序列包含第一个元素,未排序序列为其余的元素;之后每次从未排序序列中取一个元素插入已排序序列,直到未排序序列元素个数为零,排序就完成了。 下面给出代码void InsertionSort(int A[], int n){ /*A[]为待排数组,n为数组中元素个数*/ int temp原创 2017-06-11 23:27:41 · 375 阅读 · 0 评论 -
C语言 实现中缀表达式转后缀表达式并求值
大一菜鸟,初学编程,这是我的第一篇博客,希望能用博客记录我的成长之路。初学数据结构,刚接触链表和栈,看到有中缀表达式转后缀的题就试着实现了一下。下面贴上代码。因为使用的是字符型变量,所以只能计算个位数。/* 堆栈练习——中缀表达式转后缀表达式 */#include<stdio.h>#include<stdlib.h>#include<string.h>#include<stdbool.h原创 2016-04-16 18:48:57 · 15072 阅读 · 2 评论 -
【数据结构】一个数组实现两个栈
面对这个问题,我首先想到的是将一个数组的空间一分为二来为两个栈使用。可以将一个栈的底设在数组的起始位置,另一个栈的底设在数组的中间位置。但是这样并不能有效地利用数组的空间,比如当一个栈已满而另一个栈不满时,明明仍有剩余空间,却无法向前一个栈压入数据。为了能有效利用空间,考虑将两个栈的底分别设在数组的两端,这样栈顶位置由两端向中间移动保证了在数组空间被全部使用之前,元素可以压入任意一个栈中。Talk原创 2017-03-08 21:08:35 · 568 阅读 · 0 评论 -
【数据结构】栈的链表实现
1.构造结构体作为链表的节点typedef struct Node{ int Date; struct Node *Next;} LinkStack;2.建栈操作为指针S分配一块空间,返回后作为链表的头节点。其后继为空,表示栈为空。向栈中压入元素后,他的直接后继就是栈顶元素。LinkStack *CreateStack(){ LinkStack *S; S =原创 2017-03-08 20:39:07 · 691 阅读 · 0 评论 -
【数据结构】队列的链表实现
Talk is cheap, show you the code.#include <stdio.h>#include <stdlib.h>typedef struct node{ int date; struct node * Next;} Node;typedef struct queue{ Node * front; Node * rear;}* Link原创 2017-03-18 10:35:50 · 353 阅读 · 0 评论 -
【数据结构】链表及相关操作(C语言实现)
Talk is cheap, show you the code.#include <stdio.h>typedef struct Node{ int date; struct Node *Next;} List;List * CreateList() //创建一个带有空头结点的空链表{ List *p; p = (List*)malloc(sizeof(Lis原创 2017-03-08 19:09:21 · 424 阅读 · 0 评论 -
【数据结构】二叉树的中序遍历
树的遍历是指访问树的每一个结点,且每一个结点只被访问一次。访问是一个抽象的概念,实际上可以是对结点数据的各种处理,比如输出结点信息或更改结点信息。根据二叉树的构成以及结点的访问顺序,遍历可分为4种方式:先序遍历,中序遍历,后序遍历和层序遍历。 中序遍历是指对树中任意结点的访问总是在遍历完其左子树之后进行的,访问此结点后再遍历其右子树。遍历从根结点开始,遇到每个节点遍历过程如下:中序遍历其左子树原创 2017-03-22 18:17:24 · 6823 阅读 · 0 评论 -
【数据结构】二叉树的先序遍历
关于先序遍历的详细介绍参见前面关于中序遍历的博文,这里仅给出先序遍历的递归及非递归的代码实现。 如图二叉树,其先序遍历结果为:1 2 4 8 5 3 6 9 10 7Talk is cheap, show you the code. 递归实现void PreOrderTraversal(BinTree BT){ if(BT){ printf("%d ", BT->D原创 2017-03-22 19:39:28 · 602 阅读 · 0 评论 -
【数据结构】二叉树的后序遍历
后序遍历的递归实现与先序和中序遍历类似,而非递归实现较为复杂,下面会进行详细说明。 如图二叉树,其后序遍历结果为:8 4 5 2 9 10 6 7 3 1Talk is cheap, show you the code. 递归实现void PostOrderTraversal(BinTree BT){ if(BT){ PostOrderTraversal(BT->L原创 2017-03-22 22:26:24 · 1315 阅读 · 0 评论 -
【数据结构】层序生成二叉树
层序创建二叉树所用的输入序列是按树的从上到下从左到右的顺序形成的,各层的空节点输入数值0。在构造二叉树的过程中,需要一个队列暂时存储各节点,其创建过程如下。输入第一个数据: 若为0,表示此树为空,将空指针赋给根指针,树构造完毕。若不为0,动态分配一个节点单元,并存入数据,同时将该节点放入队列。若队列不为空,从队列拿出一个节点,并建立该节点的左右孩子: 从输入序列读入下一数据: 若读入数原创 2017-03-14 22:42:48 · 7319 阅读 · 1 评论 -
【数据结构】层序遍历二叉树
层序遍历二叉树的过程和层序生成二叉树的过程类似,都是要借助一个队列来实现。具体过程是:将根结点入队取出队首结点,访问该结点若该结点的左孩子非空,则将左孩子入队如果右孩子非空,将右孩子入队重复过程2,3,4 直到队列为空如图二叉树层序遍历结果为:1 2 3 4 5 6 7 8 9 10代码实现如下(此处队列的实现参见前面关于循环队列的博文)void LevelOrderTraveral(B原创 2017-03-25 16:38:51 · 918 阅读 · 0 评论 -
【数据结构】循环队列
循环队列的设计是为了避免“虚溢出”的现象。所谓“虚溢出”是指在利用数组构建队列时,当尾指针指向数组末尾时,即便数组前端仍有剩余空间,但是却无法向队列中添加新元素的“虚假溢出”的现象。图示如下:循环队列为解决“虚溢出”的问题,允许当尾指针到达数组末尾时,如果数组头部仍有空间,可以移动到数组头部并指向这些空间。所以形象地称为循环队列,并用下图表示。需要注意的是循环队列在计算机中仍然是以数组的形式顺序存储原创 2017-03-16 16:55:34 · 1458 阅读 · 0 评论 -
【数据结构】图的存储--邻接表
邻接表(Adjacency List)是图的一种顺序存储和链式存储相结合的存储方式。对于图中的每个顶点i,将所有邻接于i的顶点jlianjie成一个单向链表,这个单向链表就称为顶点i的邻接表,再将所有邻接表的表头放到一个数组中,由此就构成了图的邻接表。下面给出邻接表的结构声明#define MaxVertexNum 100 //最大顶点数为100enum GraphType {DG,UG,DN,U原创 2017-04-18 21:00:05 · 562 阅读 · 0 评论 -
【数据结构】中缀表达式转换后缀表达式(逆波兰式)
我的第一篇博文就是关于逆波兰式的,现在回头看感觉当时的代码太过混乱(不忍直视),在这里对当时的代码进行一次重构。#include <stdio.h>#include "stack.h"#define MaxSize 30int Judge(int flag,char operater){ if(flag) switch(operater){ c原创 2017-04-15 15:36:47 · 5552 阅读 · 5 评论 -
【数据结构】求K阶斐波那契数列
K阶斐波那契数列:数列第1项到第k-1项为0,第k项为1,之后从第(k+1)项开始每一项为前k项之和。要求 : 编写求k阶斐波那契序列中前n+1项(f1,f2,…,fn)的算法,要求满足fn .max,而fn +1>max,max为某个约定的常数,注意:本题所用循环队列的容量为k,算法结束时,留在队列中的元素为所求k阶斐波那契序列中的最后k项。思路:利用循环队列(令队列的长度为k)输入数列的前k原创 2017-04-15 16:29:23 · 10097 阅读 · 2 评论 -
【数据结构】图的遍历--深度优先搜索
深度优先搜索(Depth First Search,DFS)类似于树的先序遍历,是树的先序遍历的推广。 假设初始状态是图中所有顶点未被访问,则深度优先搜索可以从图的某个顶点i出发,访问此结点,然后依次从i的未被访问的邻接点出发递归地进行同样的深度优先搜索,直至图中所有和i有路径相通的顶点都被访问到;若此时图中尚有未被访问的顶点(非连通图),则另选一个未被访问的顶点作为起始点,重复上述过程,直至图中原创 2017-04-19 20:49:11 · 1106 阅读 · 0 评论 -
【数据结构】图的存储--邻接矩阵
所谓“邻接矩阵”的存储方式就是用一个一维数组存储图中全部的n个顶点的信息,用一个n×n的矩阵表示图中各顶点的邻接关系和权值。在矩阵中用1或0表示顶点间是否存在邻接关系。如果是网图的话,用0或∞表示不邻接(0可能被用作权值),用一个非零数表示权值。 根据图和矩阵的性质,该存储方式应具有以下特点:无向图的邻接矩阵一定是一个对称阵,所以在存储时只许存储矩阵的上三角即可。由于这里讨论的是简单图,所以图原创 2017-04-16 14:33:22 · 4065 阅读 · 1 评论 -
【数据结构】图的遍历--广度优先搜索
广度优先搜索过程类似于树的层次遍历,假设从图中某顶点i出发,在访问i之后依次访问i的各个未被访问的邻接点,然后从这些邻接点出发依次访问他们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直到所有顶点都被访问到(限于连通图)。如果是非连通图,则从未被访问的顶点中任选一个,再次重复上述过程。 换句话说,广度优先搜索过程中其实是以顶点i为起始点,由近及远,依次访问了与i路径原创 2017-04-21 20:29:29 · 886 阅读 · 0 评论 -
【数据结构】最大堆的插入与删除
堆是一种特殊的队列,从堆中取出元素的顺序不是按照元素进入队列的先后顺序,而是依据元素的优先权,或者说是大小,所以堆也叫做“优先队列”。 堆最常使用二叉树结构表示,可以看作是一种特殊的完全二叉树,对于一个最大堆来说可以描述为一颗所有非叶节点的子节点的值都小于该节点的完全二叉树,易得根节点的值最大,所以最大堆也叫大根堆。最小堆的描述与最大堆类似。 对于堆结构来说最大堆与最小堆的操作是类似的,所以这里原创 2017-05-23 21:45:00 · 2766 阅读 · 0 评论 -
【lintcode】删除二叉查找树的节点
描述给定一棵具有不同节点值的二叉查找树,删除树中与给定值相同的节点。如果树中没有相同值的节点,就不做任何处理。你应该保证处理之后的树仍是二叉查找树。 样例给出如下二叉查找树: 5 / \ 3 6 / \2 4删除节点3之后,你可以返回: 5 / ...原创 2018-07-15 16:06:48 · 342 阅读 · 0 评论