Java-链表(单向链表、双向链表)
Java-链表
1、什么是链表?
2、链表的特点是什么?
3、链表的实现原理?
4、如何自己写出一个链表?
1、什么是链表?
- 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的。
- 每一个链表都包含多个节点,节点又包含两个部分,一个是数据域(储存节点含有的信息),一个是引用域(储存下一个节点或者上一个节点的地址)。
- 链表的理解示意图

2、链表的特点是什么?
- 获取数据麻烦,需要遍历查找,比数组慢
- 方便插入、删除
3、链表的实现原理
- 创建一个节点类,其中节点类包含两个部分,第一个是数据域(你到时候要往节点里面储存的信息),第二个是引用域(相当于指针,单向链表有一个指针,指向下一个节点;双向链表有两个指针,分别指向下一个和上一个节点)
- 创建一个链表类,其中链表类包含三个属性:头结点、尾节点和大小,方法包含添加、删除、插入等等方法。
单向链表的节点类:
public class Node {
public Object data;
public Node next;
public Node(Object e){
this.data = e;
}
}
双向链表的节点类:
public class Node {
public Object e;
public Node next;
public Node pre;
public Node(){
}
public Node(Object e){
this.e = e;
next = null;
pre = null;
}
}
4、如何自己写出一个链表?
代码如下(以双向链表为例,有详细的注释,单向链表同理):
首先创建了一个节点类
package MutuLink;
public class Node {
public Object e;
public Node next;
public Node pre;
public Node(){
}
public Node(Object e){
this.e = e;
next = null;
pre = null;
}
}
然后创建了一个链表类
package MutuLink;
public class MyList {
private Node head;
private Node tail;
private int size = 0;
public MyList() {
head = new Node();
tail = new Node();
head.next =null;
tail.pre = null;
}
public boolean empty() {
if (head.next == null)
return true;
return false;
}
//找到所找下标节点的前一个节点
public Node findpre(int index){
Node rnode = head;
int dex = -1;
while(rnode.next != null){
//找到了插入节点的上一个节点
if( dex== index - 1){
return rnode;
}
rnode = rnode.next;
dex++;
}
return null;
}
public Node findthis(int index){
Node rnode = head;
//把rnode想象为指针,dex为指向的下标,这个地方很容易错,因为当指向最后一个节点时没有判断IF就跳出循环了
int dex = -1;
while(rnode.next != null){
if(dex == index)
return rnode;
rnode = rnode.next;
dex++;
}
if(dex == size - 1){
return rnode;
}
// Node test = new Node(new Students("haha",1,2));
return null;
}
// 往链表末尾加入节点
public void add(Object e) {
Node node = new Node(e);
Node rnode = head;
//如果是空链表的话插入一个节点,这个节点的pre不能指向上一个节点,必须指空
if (this.empty()) {
rnode.next = node;
rnode.next.pre = null;
tail.pre = node;
size++;
} else {
while (rnode.next != null)
rnode = rnode.next;
rnode.next = node;
node.pre = rnode;
tail.pre = node;
size++;
}
}
//往链表的某一个标插入一个节点
public boolean add(int index,Object e){
if(index <0||index>=size)
return false;
Node node = new Node(e);
Node prenode = this.findpre(index);
node.next = prenode.next;
prenode.next.pre = node;
prenode.next = node;
node.pre = prenode;
size++;
return true;
}
public boolean add(int index,MyList myl){
if(index <0 || index >= size)
return false;
Node prenode = this.findpre(index);
// myl.tail.pre.next = prenode.next;
// prenode.pre = myl.tail.pre;
// tail.pre = null;
// prenode.next = myl.head.next;
// myl.head.next.pre = prenode;
// head.next = null;
myl.tail.pre.next = prenode.next;
prenode.next.pre = myl.tail.pre.pre;
myl.head.next.pre = prenode.pre;
prenode.next = myl.head.next;
myl.head = null;
myl.tail = null;
size+=myl.size;
return true;
}
public Object remove(int index){
Object ob= this.get(index);
if(index <0 || index >= size)
return null;
//特殊情况,当移除节点是最后一个节点的时候
//较为复杂通过画图来写代码
if(index == size - 1){
Node prenode = this.findpre(index);
this.tail.pre = this.tail.pre.pre;
this.tail.pre.next.pre = null;
this.tail.pre.next =null;
size--;
return ob;
}
//比较复杂,通过画图解决
else{
Node prenode = this.findpre(index);
prenode.next = prenode.next.next;
prenode.next.pre.next = null;
prenode.next.pre = prenode.next.pre.pre;
size--;
return ob;
}
}
public Object get(int index){
Node thisnode = this.findthis(index);
return thisnode.e;
}
public int size(){
return size;
}
}
最后测试
package MutuLink;
import java.util.Random;
public class manage {
public static void main(String[] args) {
String name = "";
int credit;
int age;
int size;
MyList myl = new MyList();
Random random = new Random();
size = random.nextInt(5) + 1;
for (int i = 0; i < size; i++) {
credit = random.nextInt(5);
age = random.nextInt(5) + 18;
for (int j = 0; j < 4; j++) {
name += (char) (random.nextInt(26) + 97);
}
Students stu = new Students(name, credit, age);
myl.add(stu);
name = "";
}
System.out.println("Size of myl1 is "+ myl.size());
for(int i = 0; i < myl.size() ;i++){
Students stu2 = (Students) myl.get(i);
stu2.show();
}
// //测试能否在链表末尾加入节点(成功)
// for(int i = 0; i < myl.size() ;i++){
// Students stu2 = (Students) myl.get(i);
// stu2.show();
// }
// //测试能否通过下标加入一个节点(成功)
// Students stu3 = new Students("cyt",5,18);
// myl.add(1, stu3);
// System.out.println("Size is "+ myl.size());
// for(int i = 0; i < myl.size() ;i++){
// Students stu2 = (Students) myl.get(i);
// stu2.show();
// }
MyList myl2 = new MyList();
size = random.nextInt(5) + 1;
for (int i = 0; i < size; i++) {
credit = random.nextInt(5);
age = random.nextInt(5) + 18;
for (int j = 0; j < 4; j++) {
name += (char) (random.nextInt(26) + 97);
}
Students stu2 = new Students(name, credit, age);
myl2.add(stu2);
name = "";
}
System.out.println("Size is of myl2 "+ myl2.size());
for(int i = 0; i < myl2.size() ;i++){
Students stu2 = (Students) myl2.get(i);
stu2.show();
}
myl.add(1, myl2);
System.out.println("Size is of myl1 "+ myl.size());
for(int i = 0; i < myl.size() ;i++){
Students stu2 = (Students) myl.get(i);
stu2.show();
}
}
}
结果输出:

这样,一个简单的双向链表就编写完成了,希望这篇博客对您有所帮助哦!
Java-链表(单向链表、双向链表)的更多相关文章
- Java实现单向链表基本功能
一.前言 最近在回顾数据结构与算法,有部分的算法题用到了栈的思想,说起栈又不得不说链表了.数组和链表都是线性存储结构的基础,栈和队列都是线性存储结构的应用- 本文主要讲解单链表的基础知识点,做一个简单 ...
- 数据结构——Java实现单向链表
结点类: /** * @author zhengbinMac * 一个OnelinkNode类的对象只表示链表中的一个结点,通过成员变量next的自引用方式实现线性表中各数据元素的逻辑关系. */ p ...
- java实现单向链表的增、删、改、查
单向链表 作者:vashon package com.ywx.link; /** * 单向链表 * @author vashon * */ public class LinkTest { public ...
- Java实现单向链表
/* 先定义一个Node类用来存储节点的值域和指针域 * 即当前节点中的值和后面节点的方法 * 在C中就是相当与定义一个结构体类型一个数据域和指针域的方法 */class LNode{//这个写法已经 ...
- java 实现单向链表
package cn.com.factroy2; /** * 可以看做是操作链表的工具类,链表的核心结构就是节点的数据结构 * @author wanjn * */ public class Sing ...
- Java实现单向链表的增删改查
class List<T> { private class Node { private T data; private Node next; private Node(T data) { ...
- Java实现单向链表反转
public class LinkedListTest { public static void main(String[] args) { Node A = new Node("A&quo ...
- 数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现
概要 线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列.本章先介绍线性表的几个基本组成部分:数组.单向链表.双向链表:随后给出双向链表的C.C++和Java三种语言的实现. ...
- Python 单向链表、双向链表
用面向对象实现Linkedlist链表 单向链表实现append.iternodes 双向链表实现append.pop.insert.remove.iternodes 单向链表与双向链表 单向链表: ...
- 用python实现单向链表
单向链表 单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域.这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值. 表元素域ele ...
随机推荐
- android 获取http请求json数据
package com.my.gethttpjsondata; import java.io.BufferedReader;import java.io.ByteArrayOutputStream;i ...
- css取消双击选中文字
在我们在写前端页面的时候,由于手速过快(当然这都是指的老司机),会经常双击,浏览器就会默认选中你双击的文本,这种感觉有点不太好. 这个时候就用到了 user-select:none; 属性. 因为存在 ...
- Spring Data MongoDB 基础查询
有两种方式查询 BasicQuery 和 Query 一.BasicQuery BasicQuery query = new BasicQuery("{ age : { $lt : 26 } ...
- Grunt入门学习之(1) -- 环境安装
Grunt入门学习(1) - 环境安装 这周根据项目需要,在项目的基础上分模块开发了一个小的项目板块,但是在规范组织每个模块的代码和其依赖性时比较麻烦,需要一个项目板块的构建工具.各个模块都包括其对应 ...
- java笔记--多线程基础
多线程技术 --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3889579.html "谢谢-- 在java中实现多线程技术 ...
- 使用公钥和私钥实现LINUX下免密登录
linux公钥私钥实现无密码登录 首先本地主机生成公约和私钥 # ssh-keygen /生成公钥和私钥 不要更改默认路径,中途不要输入密码,直接两次回车. 2. 将生成 ...
- 在 Windows Server Container 中运行 Azure Storage Emulator(一):能否监听自定义地址?
我要做什么? 改 ASE 的监听地址.对于有强迫症的我来说,ASE 默认监听的是 127.0.0.1:10000-10002,这让我无法接受,所以我要将它改成域名 + 80 端口的方式: 放到容器中. ...
- python笔记8-多线程threading之封装式
执行函数 1.先写一个执行函数,用来实现做某件事情,不同的人吃火锅用一个参数people代替. # coding=utf-8 import threading import time def chiH ...
- Java学习---InetAddress类的学习
基础知识 1.InetAddress类 在网络API套接字,InetAddress类和它的子类型对象使用域名DNS系统,处理主机名到主机IPv4或IPv6地址的转换.如图1-1所示. 由于InetAd ...
- Android sdk manager 更新 5.0 太难了,终于解决
由于众所周知的原因,必须在hosts中增加一些网址对应,才可以更新 203.208.46.146 www.google.com 203.208.46.1 plus.google.com 203.208 ...