算法是什么(二)手写个链表(java)
算法是什么(二)手写个链表(java)
liuyuhang原创,未经允许禁止转载
目录
很多语言的API中都提供了链表实现,或者扩展库中实现了链表。
但是更多的情况下,Map(或hash)和List(非定容数组)的使用率更高。
这并非意味着链表不应该掌握或不使用了。
链表本质上是一种及其高等的数据结构展现,扩展性极强。
链表可轻松扩展成树结构,二叉树,环,栈,队列,双向队列等。
很多种数据结构都是依据链表的形式扩展出来的,虽然我知道的并不多,但是我知道链表的重要性。
所以,手写一个链表试试。
1、本质
链表的本质是Node(节点),其中保存着信息(info),前一个节点(prevNode),后一个节点(nextNode)。
和基础操作API构成
2、特性
链表为了操作的方便性,多数会将链表做成双向链表,即既包含next,又包含prev
3、基础API
链表的操作,至少需要增删改查,不然还算啥容器了:
增:默认从末尾添加,添加指定index,在首添加三种方式添加单一元素。
删:删除头,删除尾,删除指定index的元素,删除当前指针元素。
改:设置头,设置尾,设置指定index的元素,设置当前指针元素。
查:获取当前指针元素,获取首元素,获取尾元素,获取下一个元素,获取上一个元素,获取指定index的元素
有些API还提供了更多的操作:
获取当前容器的size
获取当前指针的index
迭代器
排序工具
判空
克隆
转数组
逆转
去重复
序列化
等等。。。
链表可做的操作会比想象的多的多。
4、Java中的链表
Java中常用的链表是LinkedList,实现了List接口,继承AbstractLinkedList。同时还有其他接口
同时,还有Queue大类,并非在Collection接口下,但是底层有些是使用链表实现的,功能有些是重复的。
对于需要作为原子操作的各种功能的队列来说,可以考虑。
在扩展Java中的链表的时候,有几种方式供选择:
①继承LinkedList,添加扩展算法;
②实现List,继承AbstractLinkedList,同时扩展算法;
③使用装饰模式,在构造器中调用链表的构造器,同时扩展算法;
④不受约束自己写一个吧。。。
5、写一个简单的链表
我尝试写了一个简单的链表,以前也大概看过C的链表和Java的链表,写的过程中全凭记忆,
大约花了十个小时才写完,哩哩啦啦好多天。
代码拙劣,为了以后尝试链表的其他算法(排序,转换,反转,环链表,扩展二叉树)做准备。
代码如下:
package com.FM.ArrayStudy;
public class SimpleLinkedList<T> {
private Node<T> pointer;// 当前指针节点
private Node<T> firstNode;// 首个节点
private Node<T> lastNode;// 末尾节点
private Integer index = 0;// 当前指针index
private Integer size = 0;// 当前容量
/**
* 获取当前pointer的info
* @return
*/
public T getThis() {
if (null == pointer) {
return firstNode.info;
} else {
return pointer.info;
}
}
/**
* 获取下一个元素的内容,若没有下一个元素,则返回null
*
* @return
*/
public T getNext() {
if (index.equals(size - 1)) {
return null;
} else {
if (null == pointer) {
pointer = firstNode;
pointer = pointer.next;
T info = pointer.info;
index++;
return info;
} else {
pointer = pointer.next;
T info = pointer.info;
index++;
return info;
}
}
}
/**
* 修改指定index的元素的方法
*
* @param index
* @param t
* @throws Exception
*/
public void set(Integer index, T t) throws Exception {
if (index > -1 && index < size - 1) {
Node<T> node = getNodeByIndex(index);
node.info = t;
} else {
throw new Exception("get ele " + index + " out of index");
}
}
/**
* 修改首元素
*
* @param t
*/
public void setFirst(T t) {
firstNode.info = t;
}
/**
* 修改尾元素
*
* @param t
*/
public void setLast(T t) {
lastNode.info = t;
}
/**
* 从指定index移除node的方法
*
* @param index
* @throws Exception
*/
public void remove(Integer index) throws Exception {
if (index > -1 && index < size) {
if (index.equals(0)) {
Node<T> node = getNodeByIndex(1);
firstNode = node;
firstNode.prve = null;
} else if (index.equals(size - 1)) {
Node<T> node = getNodeByIndex(size - 2);
lastNode = node;
lastNode.next = null;
} else {
Node<T> node = getNodeByIndex(index);
Node<T> nextNode = node.next;
Node<T> prveNode = node.prve;
prveNode.next = nextNode;
nextNode.prve = prveNode;
node = null;
}
size--;
} else {
throw new Exception("get ele " + index + " out of index");
}
}
/**
* 获取当前元素在链表中的位置
*
* @return
*/
public int getIndex() {
return index;
}
/**
* 获取当前链表size的方法
*
* @return
*/
public Integer size() {
return size;
}
/**
* 判断容器是否为空的方法,为空返回true
*
* @return
*/
public boolean isEmpty() {
if (size.equals(0)) {
return true;
} else {
return false;
}
}
/**
* 根据index查询链表中元素的方法
*
* @param index
* @return
* @throws Exception
*/
public T getByIndex(Integer index) throws Exception {
if (index > -1 && index < size) {
Node<T> nodeByIndex = getNodeByIndex(index);
return nodeByIndex.info;
} else {
throw new Exception("get ele " + index + " out of index");
}
}
/**
* 根据index获取node的方法
*
* @param index
* @return
*/
private Node<T> getNodeByIndex(Integer index) {
Node<T> temp = firstNode;// 取firstnode
if (index != 0) {// 查看当前index,若index!=0,则递归直到index
for (int i = 0; i < index; i++) {
temp = temp.next;
}
}
this.index = index;// 调整当前index
return temp;// 返回节点
}
/**
* 向链表末尾默认添加一个元素的方法
*
* @param t
*/
public void add(T t) {
if (size == 0) {// 首次创建
Node<T> node = new Node<T>();
firstNode = node;
lastNode = node;
node.info = t;
size++;
} else {
lastNode.next = new Node<T>();
lastNode.next.info = t;
lastNode.next.prve = lastNode;
lastNode = lastNode.next;
size++;
}
}
/**
* 在首添加元素
*
* @param t
*/
public void addFirst(T t) {
if (size == 0) {
add(t);
} else {
Node<T> node = new Node<T>();
node.info = t;
node.next = firstNode;
node.prve = null;
firstNode.next = node;
size++;
}
}
/**
* 在尾部添加元素
*
* @param t
*/
public void addLast(T t) {
add(t);
}
/**
* Node节点 链表内部数据结构和指针
*
* @author Liuyuhang
* @param <T>
*/
private class Node<T> {
T info;// 储存info
Node<T> next;// 下一个节点指针
Node<T> prve;// 上一个节点指针
@Override
public String toString() {// 同时打印next和prev会导致无限引用,堆栈溢出
return "Node [info=" + info + ", next=" + next + "]";
}
}
@Override
public String toString() {// 打印first节点会因为next引出整个链表的所有内容
return "SimpleLinkedList [node=" + firstNode + "]";
}
}
测试可用,自己拿去玩吧。
以上!
算法是什么(二)手写个链表(java)的更多相关文章
- 利用神经网络算法的C#手写数字识别(二)
利用神经网络算法的C#手写数字识别(二) 本篇主要内容: 让项目编译通过,并能打开图片进行识别. 1. 从上一篇<利用神经网络算法的C#手写数字识别>中的源码地址下载源码与资源, ...
- 利用神经网络算法的C#手写数字识别(一)
利用神经网络算法的C#手写数字识别 转发来自云加社区,用于学习机器学习与神经网络 欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 下载Demo - 2.77 MB (原始地址):handwri ...
- 利用神经网络算法的C#手写数字识别
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 下载Demo - 2.77 MB (原始地址):handwritten_character_recognition.zip 下载源码 - 70. ...
- k最邻近算法——使用kNN进行手写识别
上篇文章中提到了使用pillow对手写文字进行预处理,本文介绍如何使用kNN算法对文字进行识别. 基本概念 k最邻近算法(k-Nearest Neighbor, KNN),是机器学习分类算法中最简单的 ...
- 在opencv3中实现机器学习算法之:利用最近邻算法(knn)实现手写数字分类
手写数字digits分类,这可是深度学习算法的入门练习.而且还有专门的手写数字MINIST库.opencv提供了一张手写数字图片给我们,先来看看 这是一张密密麻麻的手写数字图:图片大小为1000*20 ...
- 二. 手写SpringMVC框架
1.1 新建DispatcherServlet 1.2 在src目录下,新建applicationContext.xml <?xml version="1.0" encodi ...
- 手写数字识别的k-近邻算法实现
(本文为原创,请勿在未经允许的情况下转载) 前言 手写字符识别是机器学习的入门问题,k-近邻算法(kNN算法)是机器学习的入门算法.本文将介绍k-近邻算法的原理.手写字符识别问题分析.手写字符识别的k ...
- 机器学习框架ML.NET学习笔记【5】多元分类之手写数字识别(续)
一.概述 上一篇文章我们利用ML.NET的多元分类算法实现了一个手写数字识别的例子,这个例子存在一个问题,就是输入的数据是预处理过的,很不直观,这次我们要直接通过图片来进行学习和判断.思路很简单,就是 ...
- java - day015 - 手写双向链表, 异常(续), IO(输入输出)
类的内存分配 加载到方法区 对象在堆内存 局部变量在栈内存 判断真实类型,在方法区加载的类 对象.getClass(); 类名.class; 手写双向链表 package day1501_手写双向链表 ...
随机推荐
- 比较全的css重设
一.最简化的CSS Reset(重设) : * { padding:; margin:; } 这是最普遍最简单的CSS重设,将所有元素的padding和margin值都设为0,可以避免一些浏览器在理解 ...
- CSS3动画功能
1.transition功能 transition属性的使用方法:transition:property duration timing-function; 其中property表示对哪个属性进行平滑 ...
- 10分钟学会Less开发环境搭建与初体验
Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量.混合(mixin).函数等功能,让 CSS 更易维护.方便制作主题.扩充. 今天看一下,10分钟能不能手把手快速教会你Le ...
- Apache Maven 3.5.0配置安装
1.maven 3.5 下载地址:http://maven.apache.org/download.cgi 2.下载了解压到 3.配置环境变量 4.测试看是否安装成功 5.maven配置(全局配置,用 ...
- jquery each() 方法跳出循环
1.jquery each() 方法 return false: 的时候 相当于 break; 跳出整个循环: 2.jquery each() 方法 return true: 的时候 相当于 ...
- hdu 3367 Pseudoforest (最大生成树 最多存在一个环)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3367 Pseudoforest Time Limit: 10000/5000 MS (Java/Oth ...
- Android 低版本sdk中没有getSupportedPreviewSizes和getSupportedPictureSizes函数怎么办?
在做camera和SurfaceView做摄像头程序时,需要获取camera支持的相片大小,在低版本sdk中没有getSupportedPictureSizes函数,怎么办呢,请参阅下面的关键代码: ...
- sqlserver批量删除表
--批量删除表 ) DECLARE tmpCur CURSOR FOR SELECT name FROM sys.objects WHERE TYPE='U' AND name LIKE N'%_Qu ...
- MySQL案例02:ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES
MySQL在授权用户时出现报错信息,具体信息如下: 一.错误信息 执行命令: GRANT SELECT,INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SH ...
- 使用DIDatepicker
使用DIDatepicker https://github.com/noxt/DIDatepicker 效果: #import "DIViewController.h" #impo ...