Java 数据结构和经典算法经验总结
来源:互联网 发布:千牛卖家第三方软件 编辑:程序博客网 时间:2024/06/05 02:00
前言:在计算机软件专业中,算法分析与设计是一门非常重要的课程,很多人为它如痴如醉。很多问题的解决,程序的编写都要依赖它,在软件还是面向过程的阶段,就有‘程序=算法+数据结构’这个公式。算法的学习对于培养一个人的逻辑思维能力是有极大帮助的,它可以培养 我们养成思考分析问题,解决问题的能力。 如果一个算法有缺陷,或不适合某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂性和时间复杂度来衡量。算法可以使用自然语言、伪代码、流程图等多种不同的方法来描述。计算机系统中的操作系统、语言编译系统、数据库管理系统以及各种各样的计算机应用系统中的软件,都必须使用具体的算法来实现。算法设计与分析是计算机科学与技术的一个核心问题。因此,学习算法无疑会增强自己的竞争力,提高自己的修为,为自己增彩。
概念:算法简单来说就是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,也就是说算法告诉计算机怎么做,以此来解决问题。同一个问题存在多种算法来解决它,但是这些算法存在着优劣之分,好的算法速度快,效率高,占用空间小,差的算法不仅复杂难懂,而且效率低,对机器要求还高,当然,有时候算法之间存在一种互补关系,有些算法效率高,节省时间,但浪费空间,另外一些算法可能速度上慢些,但是空间比较节约,这时候 我们就应该根据实际要求,和具体情况来采取相应的算法来解决问题。
一:
约瑟夫算法
约瑟夫环:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
二: 二叉树的构建及遍历
有一些博客构建出来的二叉树是完全二叉树,这篇博客什么样的二叉树都能构建,图为代码所示的一棵二叉树
public class BinaryTree { private static String [] array = {"A","B","D","H","","","I","","","E","","J","","", "C","F","","K","","","G","",""}; private static int arrayIndex = 0; // 创建一棵二叉树,约定用户遵照前序遍历的方式输入数据 // 不使用迭代是因为迭代必须要知道这棵树有多深, // 递归只需要输入就可以自行决定深度 // type:结点类型 0 根节点 1左孩子 2右孩子 public static TreeNode createBinaryTree(int type,String parentData) { switch (type) { case 0: System.out.print("根节点:"); break; case 1: System.out.print(parentData+"的左孩子:"); break; case 2: System.out.print(parentData+"的右孩子:"); break; } // 可以使用手动输入也可以放到数组里 // Scanner sc = new Scanner(System.in); // String data = sc.nextLine(); String data = ""; if(arrayIndex<array.length){ data = array[arrayIndex]; System.out.println(data); arrayIndex++; }else{ System.out.println(); } TreeNode node = null; // data为空表示没有这个孩子 if(data==null||data.equals("")){ return node; }else{ node = new TreeNode(data); node.setLchild(createBinaryTree(1,node.getData())); node.setRchild(createBinaryTree(2,node.getData())); return node; } } // 前序遍历 public static void preOrderTraverse(TreeNode node){ if(node != null){ // 根,左,右 System.out.print(node.getData()); preOrderTraverse(node.getLchild()); preOrderTraverse(node.getRchild()); } } // 中序遍历 public static void inOrderTraverse(TreeNode node){ if(node != null){ // 左,根,右 inOrderTraverse(node.getLchild()); System.out.print(node.getData()); inOrderTraverse(node.getRchild()); } } // 后序遍历 public static void postOrderTraverse(TreeNode node){ if(node != null){ // 左,右,根 postOrderTraverse(node.getLchild()); postOrderTraverse(node.getRchild()); System.out.print(node.getData()); } } // public static void main(String[] args) { TreeNode rootNode = createBinaryTree(0,""); System.out.println(); System.out.print("前序遍历:"); preOrderTraverse(rootNode); System.out.println(); System.out.print("中序遍历:"); inOrderTraverse(rootNode); System.out.println(); System.out.print("后序遍历:"); postOrderTraverse(rootNode); } } /** * 二叉树结点 * @author cmdsm * */ class TreeNode{ private String data; private TreeNode lchild; private TreeNode rchild; public TreeNode() { super(); } public TreeNode(String data) { this.data = data; } public String getData() { return data; } public void setData(String data) { this.data = data; } public TreeNode getLchild() { return lchild; } public void setLchild(TreeNode lchild) { this.lchild = lchild; } public TreeNode getRchild() { return rchild; } public void setRchild(TreeNode rchild) { this.rchild = rchild; } @Override public String toString() { return "TreeNode [data=" + data + ", lchild=" + lchild + ", rchild=" + rchild + "]"; } }
结果:三: 线索二叉树(中序)
代码所示为下图二叉树
中序遍历:CBDAEF
C,D,F有两个空指针域,E有一个
步骤如下:
1.创建二叉树
2.创建头结点
3.中序遍历线索化
4.中序遍历此线索二叉树(非递归方式)
四: 普里姆(Prim)算法
个人认为此算法遍历顺序的决定条件:
1.确定第一个顶点
2.下一个顶点可到(小于正无穷)
3.取可到顶点中最小权值的一个
代码中的图
最小生成树:99
代码(参考其他文章):
五:克鲁斯卡尔(Kruskal)算法判断是否为回路的机制没有理解
代码所示图和边集数组
代码
结果:六: 迪杰斯特拉(Dijkstra)算法
基本思想
通过Dijkstra计算图G中的最短路径时,需要指定起点vs(即从顶点vs开始计算)。
此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点,而U则是记录还未求出最短路径的顶点(以及该顶点到起点vs的距离)。
初始时,S中只有起点vs;U中是除vs之外的顶点,并且U中顶点的路径是"起点vs到该顶点的路径"。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 ... 重复该操作,直到遍历完所有顶点。
操作步骤
(1) 初始时,S只包含起点vs;U包含除vs外的其他顶点,且U中顶点的距离为"起点vs到该顶点的距离"[例如,U中顶点v的距离为(vs,v)的长度,然后vs和v不相邻,则v的距离为∞]。
(2) 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。
(3) 更新U中各个顶点到起点vs的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(vs,v)的距离可能大于(vs,k)+(k,v)的距离。
(4) 重复步骤(2)和(3),直到遍历完所有顶点。
代码示例图:
图一:
图二:
代码:
运行结果:图一
图二
七: 弗洛伊德(Floyd)算法
代码所示图:
图1:
图2:
代码:
结果:图1:
图2:
二叉树的构建及遍历
public class BinaryTree { private static String [] array = {"A","B","D","H","","","I","","","E","","J","","", "C","F","","K","","","G","",""}; private static int arrayIndex = 0; // 创建一棵二叉树,约定用户遵照前序遍历的方式输入数据 // 不使用迭代是因为迭代必须要知道这棵树有多深, // 递归只需要输入就可以自行决定深度 // type:结点类型 0 根节点 1左孩子 2右孩子 public static TreeNode createBinaryTree(int type,String parentData) { switch (type) { case 0: System.out.print("根节点:"); break; case 1: System.out.print(parentData+"的左孩子:"); break; case 2: System.out.print(parentData+"的右孩子:"); break; } // 可以使用手动输入也可以放到数组里 // Scanner sc = new Scanner(System.in); // String data = sc.nextLine(); String data = ""; if(arrayIndex<array.length){ data = array[arrayIndex]; System.out.println(data); arrayIndex++; }else{ System.out.println(); } TreeNode node = null; // data为空表示没有这个孩子 if(data==null||data.equals("")){ return node; }else{ node = new TreeNode(data); node.setLchild(createBinaryTree(1,node.getData())); node.setRchild(createBinaryTree(2,node.getData())); return node; } } // 前序遍历 public static void preOrderTraverse(TreeNode node){ if(node != null){ // 根,左,右 System.out.print(node.getData()); preOrderTraverse(node.getLchild()); preOrderTraverse(node.getRchild()); } } // 中序遍历 public static void inOrderTraverse(TreeNode node){ if(node != null){ // 左,根,右 inOrderTraverse(node.getLchild()); System.out.print(node.getData()); inOrderTraverse(node.getRchild()); } } // 后序遍历 public static void postOrderTraverse(TreeNode node){ if(node != null){ // 左,右,根 postOrderTraverse(node.getLchild()); postOrderTraverse(node.getRchild()); System.out.print(node.getData()); } } // public static void main(String[] args) { TreeNode rootNode = createBinaryTree(0,""); System.out.println(); System.out.print("前序遍历:"); preOrderTraverse(rootNode); System.out.println(); System.out.print("中序遍历:"); inOrderTraverse(rootNode); System.out.println(); System.out.print("后序遍历:"); postOrderTraverse(rootNode); } } /** * 二叉树结点 * @author cmdsm * */ class TreeNode{ private String data; private TreeNode lchild; private TreeNode rchild; public TreeNode() { super(); } public TreeNode(String data) { this.data = data; } public String getData() { return data; } public void setData(String data) { this.data = data; } public TreeNode getLchild() { return lchild; } public void setLchild(TreeNode lchild) { this.lchild = lchild; } public TreeNode getRchild() { return rchild; } public void setRchild(TreeNode rchild) { this.rchild = rchild; } @Override public String toString() { return "TreeNode [data=" + data + ", lchild=" + lchild + ", rchild=" + rchild + "]"; } }结果:
三: 线索二叉树(中序)
代码所示为下图二叉树
中序遍历:CBDAEF
C,D,F有两个空指针域,E有一个
步骤如下:
1.创建二叉树
2.创建头结点
3.中序遍历线索化
4.中序遍历此线索二叉树(非递归方式)
普里姆(Prim)算法
个人认为此算法遍历顺序的决定条件:
1.确定第一个顶点
2.下一个顶点可到(小于正无穷)
3.取可到顶点中最小权值的一个
代码中的图
最小生成树:99
代码(参考其他文章):
五:克鲁斯卡尔(Kruskal)算法判断是否为回路的机制没有理解
代码所示图和边集数组
代码
结果:六: 迪杰斯特拉(Dijkstra)算法
基本思想
通过Dijkstra计算图G中的最短路径时,需要指定起点vs(即从顶点vs开始计算)。
此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点,而U则是记录还未求出最短路径的顶点(以及该顶点到起点vs的距离)。
初始时,S中只有起点vs;U中是除vs之外的顶点,并且U中顶点的路径是"起点vs到该顶点的路径"。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 ... 重复该操作,直到遍历完所有顶点。
操作步骤
(1) 初始时,S只包含起点vs;U包含除vs外的其他顶点,且U中顶点的距离为"起点vs到该顶点的距离"[例如,U中顶点v的距离为(vs,v)的长度,然后vs和v不相邻,则v的距离为∞]。
(2) 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。
(3) 更新U中各个顶点到起点vs的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(vs,v)的距离可能大于(vs,k)+(k,v)的距离。
(4) 重复步骤(2)和(3),直到遍历完所有顶点。
代码示例图:
图一:
图二:
代码:
运行结果:
图一
图二
七:
弗洛伊德(Floyd)算法
代码所示图:
图1:
图2:
代码:
图1:
图2:
- Java 数据结构和经典算法经验总结
- java 数据结构经典算法
- 数据结构和经典算法
- 经典数据结构和算法
- 数据结构和算法经典书籍
- 经典数据结构和算法回顾
- 经典数据结构和算法回顾
- 数据结构和算法经典书籍
- JAVA数据结构和算法
- Java 数据结构和算法
- java 数据结构和算法
- Java数据结构和算法
- java数据结构和算法
- Java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- Git 的命令操作
- window.open不生效
- css3 制作三角
- 论文的页码设置
- SSIS package 更新 variable
- Java 数据结构和经典算法经验总结
- 微服务可靠性设计
- 【NGUI】各个组件的应用与数值获取
- post和get请求
- 莫名原因的报错
- sdut 2168 Mathmen 贪心
- java-枚举
- cxf-spring-pratice-service
- 一次SSIS Package的调试经历