1.准备链表准备一个由 DataNode 组成的单向链表,DataNode 如下:csharp 代码解读复制代码 public class DataNode {
private int data;
private DataNode next;
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public DataNode getNext() {
return next;
}
public void setNext(DataNode next) {
this.next = next;
}
public DataNode(int data) {
this.data = data;
}
复制代码
}
构造链表 ini 代码解读复制代码 public class DataChain {
private DataNode head;
public DataChain(int size) {
DataNode head = new DataNode(0);
DataNode cur = head;
for (int i = 1; i < size; i++) {
DataNode tmp = new DataNode(i);
cur.setNext(tmp);
cur = tmp;
}
this.head = head;
}
public DataNode getHead() {
return head;
}
public void setHead(DataNode head) {
this.head = head;
}
public static void printChain(DataNode head) {
StringBuilder sb = new StringBuilder();
DataNode cur = head;
sb.append(cur.getData());
while (null != cur.getNext()) {
sb.append(" -> ");
sb.append(cur.getNext().getData());
cur = cur.getNext();
}
System.out.println(sb.toString());
}
public static void main(String... strings) {
DataChain chain = new DataChain(10);
printChain(chain.getHead());
}
复制代码
}
运行 main 方法,即构造了一个包含 10 个 node 节点的单链表。rust 代码解读复制代码 #运行结果 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9
2.通过递归实现单链表反转考虑到代码的简洁性,首先考虑的是通过递归实现。java 代码解读复制代码 /**
* 递归实现 当栈深度大于12000 则会出现StakOverflowError
*
* @param head
* @return
*/
public static DataNode reverse1(DataNode head) {
if (null == head || null == head.getNext())
return head;
DataNode revHead = reverse1(head.getNext());
head.getNext().setNext(head);
head.setNext(null);
return revHead;
}
复制代码
以上即是递归实现的源码,但是需要考虑的问题是递归都在 java 栈中进行,需要考虑 jdk 支持的栈的深度。在 jdk1.8.0_91 版本中,当上述链表长度大于 12000 则会出现 StackOverFlowError 错误。说明对于该版本 jdk 栈的深度不能大于 12000。3.通过遍历实现最通用的实现方式就是遍历。ini 代码解读复制代码/**
* 遍历实现 通用实现方法
*
* @param head
* @return
*/
public static DataNode reverse2(DataNode head) {
if (null == head || null == head.getNext())
return head;
DataNode pre = head;
DataNode cur = head.getNext();
while (null != cur.getNext()) {
DataNode tmp = cur.getNext();
cur.setNext(pre);
pre = cur;
cur = tmp;
}
cur.setNext(pre);
head.setNext(null);
return cur;
}
复制代码
4.借助 stack 实现考虑到 stack 具有先进后出这一特性,因此可以借助于 stack 数据结构来实现单向链表的反转。ini 代码解读复制代码/**
* 方法3 利用其他数据结构 stack
* @param head
* @return
*/
public static DataNode reverse3(DataNode head) {
Stack<DataNode> stack = new Stack<DataNode>();
for (DataNode node = head; null != node; node = node.getNext()) {
stack.add(node);
}
DataNode reHead = stack.pop();
DataNode cur = reHead;
while(!stack.isEmpty()){
cur.setNext(stack.pop());
cur = cur.getNext();
cur.setNext(null);
}
return reHead;
}
复制代码
上述实现方法在于操作简单,对于算法并不精通的同学可以尝试。缺点在于需要通过其他数据结构实现,效率会降低,至于效率会降低到什么程度,后面举例说明。5.三种实现方式效率分析 ini 代码解读复制代码 public static void main(String... strings) {
int size = 10;
DataChain chain1 = new DataChain(size);
printChain(chain1.getHead());
long reverse1_start = System.currentTimeMillis();
DataNode reNode1 = reverse1(chain1.getHead());
long reverse1_cost = System.currentTimeMillis() - reverse1_start;
printChain(reNode1);
System.out.println("reverse1 cost time is ["+reverse1_cost+"]ms");
DataChain chain2 = new DataChain(size);
printChain(chain2.getHead());
long reverse2_start = System.currentTimeMillis();
DataNode reNode2 = reverse2(chain2.getHead());
long reverse2_cost = System.currentTimeMillis() - reverse2_start;
printChain(reNode2);
System.out.println("reverse2 cost time is ["+reverse2_cost+"]ms");
DataChain chain3 = new DataChain(size);
printChain(chain3.getHead());
long reverse3_start = System.currentTimeMillis();
DataNode reNode3 = reverse3(chain3.getHead());
long reverse3_cost = System.currentTimeMillis() - reverse3_start;
printChain(reNode3);
System.out.println("reverse3 cost time is ["+reverse3_cost+"]ms");
}
复制代码
执行结果:rust 代码解读复制代码 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 99 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0reverse1 cost time is [0]ms0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 99 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0reverse2 cost time is [0]ms0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 99 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0reverse3 cost time is [1]ms
在上述代码基础上,去掉打印输出,将 size 改为 10000,结果如下:css 代码解读复制代码 reverse1 cost time is [1]msreverse2 cost time is [0]msreverse3 cost time is [6]ms
可以看出 reverse2 明显优于其他两种实现方法。考虑到 reverse1 最多只支持 12000,因此将 size 改为 100000 时,再观察 reverse2 和 reverse3 之间的执行结果:css 代码解读复制代码 reverse2 cost time is [6]msreverse3 cost time is [25]ms
因此可以看出,最好的方法是采用遍历的方式进行反转。
行业拓展
近 10 年间,甚至连传统企业都开始大面积数字化时,我们发现开发内部工具的过程中,大量的页面、场景、组件等在不断重复,这种重复造轮子的工作,浪费工程师的大量时间。 针对这类问题,JNPF 低代码平台把某些重复出现的场景、流程,具象化成一个个组件、api、数据库接口,避免了重复造轮子,极大的提高了程序员的生产效率。
体验地址:https://www.jnpfsoft.com
这是一个基于 Flowable 引擎(支持 java、.NET),已支持 MySQL、SqlServer、Oracle、PostgreSQL、DM(达梦)、 KingbaseES(人大金仓)6 个数据库,支持私有化部署,前后端封装了上千个常用类,方便扩展,框架集成了表单、报表、图表、大屏等各种常用的 Demo 方便直接使用。
至少包含表单建模、流程设计、报表可视化、代码生成器、系统管理、前端 UI 等组件,这种情况下我们避免了重复造轮子,已内置大量的成熟组件,选择合适的组件进行集成或二次开发复杂功能,即可自主开发一个属于自己的应用系统。
评论