数据结构
文章平均质量分 71
自己学习数据结构的思路和代码整理
独行的喵
这个作者很懒,什么都没留下…
展开
-
二叉树的中序非递归遍历
二叉树的中序非递归遍历中序遍历的非递归算法描述如下:从根节点开始检索,如果当前节点不为空,则将当前节点入栈,让当前节点成为其左孩子节点,再继续上一步的操作加入当前节点为空了,说明其父节点已经没有左孩子了,那么将栈顶元素出栈并输入判断栈顶元素是否有右孩子,如果有右孩子,则停止依次继续出栈的操作,并检索它的右孩子,重复第一步;如果没有右孩子,则继续将栈顶元素出栈当栈为空,并且当前节点为空时,遍历完成,退出;#include<stdio.h>#include<stdlib.h&原创 2021-09-17 18:01:56 · 8314 阅读 · 3 评论 -
栈和队列——表达式求值大全
表达式求值一.关于三种表达式的分类中缀表达式:即我们最为常见的表达式,运算符号位于参与运算的连个操作数中间的表达式称作中缀表达式前缀表达式:前缀表达式是一种没有括号的算术表达式,与中缀表达式不同的是,其将运算符写在前面,操作数写在后面。为纪念其发明者波兰数学家Jan Lukasiewicz,前缀表达式也称为“波兰式”。例如,- 1 + 2 3,它等价于1-(2+3)。后缀表达式:指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则原创 2021-11-25 17:59:51 · 1859 阅读 · 9 评论 -
java五子棋AI算法人机对战(春物彩羽版可下载试玩PC端)
五子棋AI算法前言:坐标西安,写于疫情封城期间。改进了之前写的基于极大极小值策略AI五子棋游戏,是用java实现的,采用了java老旧的jframe窗体和绘图类。写好之后整理成了这篇博客。游戏采用了春物二次元风格,内置彩羽语音,强度的话还不错,不好下赢,防守为主。文章中的代码部分并不完整,只是摘出了主要部分说明思路,完整代码可以到文末链接处下载。悔棋和认输功能没有去写目录:1.五子棋下棋功能的实现1.1五子棋棋盘的绘制1.2落子功能的实现1.3棋局输赢的判断2.AI下棋算法的实现原创 2022-01-24 10:31:58 · 1704 阅读 · 0 评论 -
单调栈——力扣84题
单调栈我们从力扣84题的解决思路中引出单调栈的概念,首先看力扣84题的题目描述如下:关于暴力解:这道题是要寻找最大的而矩形区域,暴力的解法是:以每一个柱子为基准,寻找包含该柱子的最大矩形区域。即遍历到每一个柱子时,寻找以它的高度为高,宽度最大的矩形。这样的做法十分简单,但是遍历柱子的时间复杂度是O(N),而寻找包含每一根柱子的矩形最大宽度的时间复杂度也是O(N),这样一来总的算法的时间复杂度是O(N^2)算法的改进:能否将该问题的时间复杂度缩减到O(N)?即我们尽可能地通过一次对所有柱子的遍历来解决问原创 2021-12-15 11:59:08 · 5192 阅读 · 0 评论 -
KMP算法
简单模式匹配算法(暴力匹配)在简单的模式匹配算法中,我们使用的是一种暴力求解的匹配思路。假设有主串S1和模式串S2,在S2向S1匹配的过程中,一但一次匹配失败,我们需要回溯主串的位置进行重新匹配:假设在这样的位置比较失败了,这次主串比较的起始位置为1,那么在下次重新比较的时候需要从下一个起始位置2开始对模式串重新比较匹配。这样的算法简单但是暴力,其算法的时间复杂度为O(nm)其中n为主串长度,m为模式串的长度。KMP算法KMP算法是对字符串的简单模式匹配算法的一种改进其思想是只让模式串的比原创 2021-09-14 17:26:13 · 309 阅读 · 1 评论 -
堆排序c语言
堆排序堆排序是基于堆的数据结构将待排序元素进行处理的一种排序堆的一棵具有特殊性质的完全二叉树:该二叉树具有堆序性,即任何一个节点的值大于等于其孩子节点(或小于等于其孩子节点的值);如果任一节点的值大于孩子节点的值,这样的完全二叉树称为大根堆;如果任意节点的值小于等于其孩子节点的值,这样的完全二叉树称为小根堆。基于上面的定义,不难得到堆一定具有这样的性质:堆顶元素一定是堆中最大或者最小的元素,所以我们可以不断输出堆顶元素,并时刻维护这个堆,就能保证我们每次输出的堆顶元素依次是待排序列中的最值。这样一来不原创 2021-09-04 12:31:31 · 128 阅读 · 0 评论 -
插入排序与希尔排序
插入排序思路:将未排序的元素逐个插入到已排序的元素中,使其保持有序:假设前i个元素有序(初始时默认第一个元素一定是有序的)而后n-i个元素无序,那么从第n-i个元素开始逐个将无序元素插入到有序元素当中,并保持有序元素集仍保持有序,从而使有序元素集不断增加,使无序元素集不断减少,直到全部元素都保持有序为止。#include <stdio.h>#include <stdlib.h>//插入排序void InsertionSort(int array[],int leng原创 2021-08-15 23:24:48 · 132 阅读 · 0 评论 -
打家劫舍1
打家劫舍1一种最容易想到的,用类似深搜的方法来解决的低效算法:#include<stdio.h>#include<stdlib.h>//深搜解决打家劫舍问题 int dp(int start,int n,int nums[]){ if(start>=n) return 0; return dp(start+1,n,nums)>=nums[start]+dp(start+2,n,nums)?dp(start+1,n,nums):nums[start]+d原创 2021-06-17 12:01:06 · 124 阅读 · 0 评论 -
哈希表(散列)
哈希表(散列)定义哈希表哈希表(散列表)是一种将关键字key与地址或其它数据建立起直接映射关系的数据结构。哈希表通过哈希函数(hash函数)将关键字key进行运算并映射到散列表中的某一位置,建立起这样的映射关系可以加快对数据的查找和访问。哈希函数哈希函数的功能是建立其关键字key与哈希表中存储位置的映射关系。将关键字按一定算法转换成数值,再对数值做一定处理得出hashcode,hashcode代表了数据对象在哈希表中存储的索引位置index。一个好的hash函数应具备两个条件:尽可能地将数据原创 2021-06-08 10:53:04 · 778 阅读 · 0 评论 -
线索二叉树
线索二叉树线索二叉树的概念:1.线索:线索是一种对二叉树的操作,意思是对二叉树进行线索化,其目的是使线索化后的二叉树具有方便被遍历的特点,被线索化后的二叉树实际上是一个双向链表。2.基于中序遍历的线索二叉树:中序遍历,即先遍历节点的左孩子,再遍历节点本身,最后遍历节点的右孩子。3.前驱与后继:基于这样的顺序得到的对所有节点的遍历顺序中,在某一节点前一个被遍历的节点称之为该节点的前驱,而在该节点后一个被遍历的节点称之为该节点的后继。4.线索化节点的标记:线索二叉树的节点定义有所改变,需要两个原创 2021-05-18 12:20:42 · 15416 阅读 · 10 评论 -
哈夫曼编码与哈夫曼算法
哈夫曼编码与哈夫曼算法哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)哈夫曼编码在文件压缩上的应用:哈夫曼编码可以运用在对文件字符的编码上,以实现对文件的压缩。加入一个文件中存在a,b,c,d,e这几种字符,文件的整体是由这5中字符构成的,如果我们要用二进制原创 2021-05-12 10:28:34 · 2372 阅读 · 0 评论 -
Dijkstra算法
Dijkstra算法从一个已知的起始s节点开始,选择当前未知节点中到起始节点路径最短的那个节点v,比较对于每一个节点i,如果有d[i]>d[v]+e[v][i] ,则更新d[i]的值为d[v]+e[v][i](其中d[i]表示从起始节点s到节点i的最短距离,d[v]表示从起始节点s到节点v的最短距离,e[v][i]表示从v节点到i节点的这条边的距离)完成之后将节点v标记为已知。之后再从距离更新过的未知节点当中选择下一个到s距离最短的节点作为v重复之前的步骤直到所有节点都被标记为已知。#inc原创 2021-05-11 19:28:49 · 134 阅读 · 0 评论 -
孩子链表表示法表示二叉树
孩子链表表示法表示二叉树二叉树的孩子链表表示法顾名思义,就是用链表去存储和表示每一个二叉树节点的全部孩子。相比较一般常用的指针法表示二叉树节点的孩子而言,孩子链表表示法用指向一个一个链表的头节点或者是链表中第一个孩子节点的指针来替代原来的分别指向leftchild和rightchild的指针,该种表示方法的好处在于当该树并非二叉树,而是多叉树特别当一些节点的孩子数目不确定且非常多时,定义多个指向每个孩子节点的指针来表示孩子肯定是行不通的,这时用孩子链表去表示这些数目不确定且繁多的孩子时将会非常合理,不过原创 2021-05-11 17:12:46 · 4076 阅读 · 0 评论 -
图论——最小生成树
最小生成树什么是最小生成树:1.生成树:在一张无向连通有权图中,我们要从一个节点出发,找到一组有权边,将所有节点都连接起来,这样的一组节点和边将构成一颗树,也就是生成树,这颗树是根据图而生成的。2.最小生成树:在所有生成树中,如果其中一棵树的所有边的权值和最小,那么就成为最小生成树,不过最小生成树可能不是唯一的。下图中加粗的边就构成了一颗最小生成树。获得最小生成树的两种算法...原创 2021-04-26 20:41:57 · 2118 阅读 · 4 评论 -
关于求最大公倍数的不同算法比较
关于求最大公倍数的不同算法比较如果想要求两个正整数a和b的最大公倍数,我们可以想到多种求解的方法,下面给出两种比较常见的算法实现:第一种,直接循环求解:其求解思路很简单,先让最大公倍数等于a和b中较大的那一个,因为最大公倍数最小也是这样的数。然后将最大公倍数lcm++循环,如果lcm增大到某一个可以同时将a和b都分别整除时,这样遇见的第一个lcm的值就是其最大公倍数,并返回其值。这一算法的最坏时间复杂度为NMint lcm(int a, int b){ int lcm=a>b ? a :原创 2021-04-25 20:59:01 · 2594 阅读 · 0 评论 -
图论——Floyd-Warshall算法
# 前言我学习弗洛伊德算法的起因是遇到了这样一道关于最短路径的问题:在此之前,有关图论最短路径的算法,我只学习过深度优先搜索和广度优先搜索,而这两种算法获取最短路径的过程,无非都是将全部的从起点到终点的可能路径完全搜索出来,然后从中不断挑选更新最短的路径,这样的方法在小规模的图中是完全适用的,但是在上面这样的题中,如果我们使用这两种方法将会发生什么?其结果是令人难堪的,因为根据题意,搜索的结果将等价于用先序或者层序的方式去完全展开一颗十分巨大的树,这棵树将会有近乎100层...原创 2021-04-21 20:03:50 · 933 阅读 · 0 评论 -
图论——深度优先搜索
图论——深度优先搜索什么是深度优先搜索:深度优先搜素是对先序遍历的一种推广,和广度优先搜索不同,深度优先搜素的搜索顺序是先遍历当前节点,然后下次只先探索一个当前节点的临近节点,然后重复刚才的过程,直到达到最大深度,也就是不存在临近节点的情况,才算完成其中的一次搜索,我们这里回忆对比广度优先搜索,广度优先搜索的不同在于,可以将遍历每一层节点定义为一次探索,也就是每一次搜索中,我们都要将当前节点的全部临近节点都找出来才算完成一次搜索,而深度优先搜索是一直一个节点一个节点地向下探索临近节点,直到碰到死胡同才完原创 2021-04-17 18:44:33 · 3336 阅读 · 0 评论 -
图论——广度优先搜索
广度优先搜索(BFS)自己对于广度优先搜索的理解:与深度优先搜索(DFS)相对应,广度优先搜索是指,立足于当前的某一个节点,每一次将遍历所有离该节点最近的节点(也就是距离为1的节点),然后再将这些刚刚被当作最近节点遍历的节点全部依次作为当前节点进行下一次对所有最近节点的遍历,依次类推,直到找到想要的节点和路径。从我自己的算法描述可以看出,广度优先搜索是一种顾名思义的算法,类似于层序遍历,即每一次的搜索都将达到最广的范围,也就是每次都将触手可及的所有节点都找到,就像展开一颗一层一层排列的树一样。为了更原创 2021-04-15 10:26:53 · 1273 阅读 · 0 评论 -
图论——拓扑排序
拓扑排序什么是拓扑排序来自百度百科的解释:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。实际上简单的来讲就是在有向图中找到这样一个节点的有序序列,使得序列中原创 2021-04-08 16:57:27 · 1101 阅读 · 0 评论 -
图论基本概念
数据结构中图论的基本概念这一篇开始图论的初步学习图论中的一些定义:图:G=(V,E)V为图中所有顶点组成的集合 。E为图中所有边(弧)组成的集合,每一条边可以由一个点对(v,w)表示。有向图和无向图:如果边带有方向性,即表示边的点对(v,w)是有序的,那么这样的图称为有向图,反之则曾为无向图。简单路径:一条路径上包含的点除了第一个点和最后一个点以外都是互异的,不能存在重复,而第一个点和最后一个点可以重复,也可以不重复。联通:如果从无向图中任意两个节点间都存在一条路径,则称该图是联通的强连原创 2021-04-08 14:53:14 · 432 阅读 · 0 评论 -
优先队列(堆)详细整理学习
什么是优先队列优先队列是一种抽象数据结构,在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆数据结构来实现。 ———— 百度百科优先队列至少具有的2种基本操作:insert(); ——插入操作deleteMin(); ——删除最小元素的操作(其实也可以是最大元素)优先队列的实现最普遍的实现——二叉堆二叉堆的定义:二叉堆是一棵拥有特殊性质的完全二叉树(堆序性)原创 2021-03-27 12:44:03 · 611 阅读 · 1 评论 -
二叉查找树(二叉排序树)
二叉查找树(二叉排序树)二叉排序树的定义二叉排序树是这样一颗二叉树:对于树中的每一个节点x,它的左子树中的所有项的值小于该节点x的值,它的右子树中的所有项的值大于节点x的值。基于这样的性质,中序遍历该树可以得到一个从小到大排列的有序数列。下面直接讨论二叉查找树的创建过程二叉查找树的节点定义并没有不同于一颗普通的二叉树:typedef struct BSTnode{int data;struct BSTnode * left;struct BSTnode * right;}BSTnode原创 2021-04-01 16:19:15 · 954 阅读 · 2 评论 -
平衡二叉树AVL树
平衡二叉树(AVL树)定义:AVL树是一颗特殊的二叉查找树,它具有保持平衡要求的特性,AVL树的每一个节点的左子树和右子树的高度差要求最大为1,如果超过1将破坏平衡特性,将不再是一颗平衡二叉树。平衡条件的维持:为什么需要维持平衡:AVL树需要时刻保持其平衡的特性,但这样的特性可能会在插入和删除的同时被打破,插入和删除新的节点造成的高度变化可能会使某些节点的左右子树的高度差超过1,所以我们需要在插入和删除的同时维护AVL树的平衡特性。讨论如何维持AVL树的平衡:明确平衡被破坏的位置在讨论AV原创 2021-04-06 16:40:21 · 1492 阅读 · 0 评论