一、单链表基本概念

单链表是一种链式存取的数据结构,用一组地址任意的存储单元(一般是非连续存储单元)存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素data + 指针next(指示后继元素存储位置)。其存储结构如图:

二、JAVA实现单链表

数据结构:

单链表有一个属性head和一些重要的方法,head为链表结点Node类的实例。Node类中包含成员变量:data,next。data为当前节点的数据域,next为指针域,指向下一个结点。

1、结点

 class Node{
int data;
Node next=null;
public Node(int data){
this.data=data;
}
public Node(){}
public void display() {
System. out.print(this.data + " "); //结点打印函数
}
}

2、单链表

 public class linkList {
Node head=new Node();
//各种方法的实现代码
}

函数

1、链表添加元素之头插

每次来了新元素将其插入到头结点之后

 public void insertHead(int val){
Node newnode=new Node(val);
if(head.next!=null){
newnode.next=head.next;
}
head.next=newnode;
}

2、链表添加元素之尾插

每次来了新元素将其插入到链表最后位置

 public void insertTail(int val){
Node newnode=new Node(val);
Node walkPointer=head;
while(walkPointer.next!=null){
walkPointer=walkPointer.next;
}
walkPointer.next=newnode;
}

3、任意位置插入

 public void insert(int pos,int val){
int index=0;
if(pos>=0&&pos<=this.getLength()){
Node walkPointer=head;
while(index!=pos){
walkPointer=walkPointer.next;
index++;
}
Node newnode=new Node(val);
newnode.next=walkPointer.next;
walkPointer.next=newnode;
}
}

4、获取链表长度

 public int getLength(){
int length=0;
Node walkPointer=head;
while(walkPointer.next!=null){
walkPointer=walkPointer.next;
length++;
}
return length;
}

5、删除指定结点(头指针未知):实质用该结点代替其next结点

 public boolean delete(Node delnode){
if(delnode==null||delnode.next==null){
return false;
}
delnode=delnode.next;
return true;
}

6、遍历链表

 public void print() {
Node walkPointer=head;
System.out.println("**链表结点遍历**");
while(walkPointer.next!=null){
walkPointer=walkPointer.next;
System.out.print(walkPointer.data + " ");
}
System.out.println();
}

7、链表逆置

之前遇到一道题目,需要将链表元素从尾到头创建ArrayList数组的题目,这里相同的思路,只不过是逆序输出创建新的链表。

两者不同之处在于:对于非递归的方式,链表逆序输出创建新数组时,采用头插的方式相对费时,需要将第一个元素之后的元素后移;而链表逆序输出创建新链表时,采用头插的方式相对快速,只要找到头结点即可一步插入。相反的,对于递归的方式,链表逆序输出创建新数组时,采用尾插的方式相比创建新链表要省时。

思路1:(递归)将链表结点的数据顺序取出存储在栈中——从栈中pop元素采用尾插的方式建立新链表(链表的尾插比较费时,需要遍历到链表最后一个元素才能插入元素)

public linkList reverse1(){
linkList list=new linkList();
Stack<Integer> stack=new Stack<Integer>();
Node walkPointer=head.next;
while(walkPointer!=null){
stack.push(walkPointer.data);
walkPointer=walkPointer.next;
}
while(!stack.empty()){
list.insertTail(stack.pop());
}
return list;
}

思路2:(非递归)声明新链表,将原链表元素顺序取出,同时采用头插的方式插入到新链表中(链表的头插相对于尾插耗时更小)

 public linkList reverse(){
linkList list=new linkList();
Node walkPointer=head.next;
Node temp=new Node();
while(walkPointer!=null){
list.insertHead(walkPointer.data);
walkPointer=walkPointer.next;
}
return list;
}

整体代码(含测试)

 package struct;

 import java.util.Stack;

 class Node{
int data;
Node next=null;
public Node(int data){
this.data=data;
}
public Node(){}
public void display() {
System. out.print(this.data + " "); //结点打印函数
}
}
public class linkList {
Node head=new Node();
//头插
public void insertHead(int val){
Node newnode=new Node(val);
if(head.next!=null){
newnode.next=head.next;
}
head.next=newnode;
} //尾插
public void insertTail(int val){
Node newnode=new Node(val);
Node walkPointer=head;
while(walkPointer.next!=null){
walkPointer=walkPointer.next;
}
walkPointer.next=newnode;
} //获得链表长度
public int getLength(){
int length=0;
Node walkPointer=head;
while(walkPointer.next!=null){
walkPointer=walkPointer.next;
length++;
}
return length;
} //任意位置插入
public void insert(int pos,int val){
int index=0;
if(pos>=0&&pos<=this.getLength()){
Node walkPointer=head;
while(index!=pos){
walkPointer=walkPointer.next;
index++;
}
Node newnode=new Node(val);
newnode.next=walkPointer.next;
walkPointer.next=newnode;
}
} //链表的逆置(非递归,同从尾到头构建列表,链表的头插复杂度比列表头插低很多)
public linkList reverse(){
linkList list=new linkList();
Node walkPointer=head.next;
Node temp=new Node();
while(walkPointer!=null){
list.insertHead(walkPointer.data);
walkPointer=walkPointer.next;
}
return list;
//笨方法
// Node preNode=head;
// Node walkPointer=head.next;
// head.next=null;
// Node nextNode=new Node();
// while(walkPointer!=null){
// nextNode=walkPointer.next;
// walkPointer.next=preNode;
// preNode=walkPointer;
// walkPointer=nextNode;
// }
// list.head.next=preNode;
// return list;
} //链表的逆置(递归,使用栈。类似于从尾到头输出列表)
public linkList reverse1(){
linkList list=new linkList();
Stack<Integer> stack=new Stack<Integer>();
Node walkPointer=head.next;
while(walkPointer!=null){
stack.push(walkPointer.data);
walkPointer=walkPointer.next;
}
while(!stack.empty()){
list.insertTail(stack.pop());
}
return list;
} //删除指定结点(头指针未知),实质用该结点代替其next结点
public boolean delete(Node delnode){
if(delnode==null||delnode.next==null){
return false;
}
delnode=delnode.next;
return true;
} //打印遍历
public void print() {
Node walkPointer=head;
System.out.println("**链表结点遍历**");
while(walkPointer.next!=null){
walkPointer=walkPointer.next;
System.out.print(walkPointer.data + " ");
}
System.out.println();
}
@SuppressWarnings("null")
public static void main(String []args){
linkList list=new linkList();
list.insertHead(12);
list.insertHead(15);
list.insertHead(2);
list.insertHead(3);
list.insert(0,4);
list.print();
System.out.println("链表长度");
System.out.println(list.getLength());
System.out.println("!!链表转置后的头结点数据!!");
linkList returnlist=new linkList();
returnlist=list.reverse();
returnlist.print();
returnlist=list.reverse1();
returnlist.print();
}
}

数据结构之单链表的实现-java的更多相关文章

  1. 数据结构(一) 单链表的实现-JAVA

    数据结构还是很重要的,就算不是那种很牛逼的,但起码得知道基础的东西,这一系列就算是复习一下以前学过的数据结构和填补自己在这一块的知识的空缺.加油.珍惜校园中自由学习的时光.按照链表.栈.队列.排序.数 ...

  2. 数据结构(2):单链表学习使用java实现

    单链表是单向链表,它指向一个位置: 单链表常用使用场景:根据序号排序,然后存储起来. 代码Demo: package com.Exercise.DataStructure_Algorithm.Sing ...

  3. 数据结构之单链表(基于Java实现)

    链表:在计算机中用一组任意的存储单元存储线性表的数据元素称为链式存储结构,这组存储结构可以是连续的,也可以是不连续的,因此在存储数据元素时可以动态分配内存. 注:在java中没有指针的概念,可以理解为 ...

  4. Python数据结构之单链表

    Python数据结构之单链表 单链表有后继结点,无前继结点. 以下实现: 创建单链表 打印单链表 获取单链表的长度 判断单链表是否为空 在单链表后插入数据 获取单链表指定位置的数据 获取单链表指定元素 ...

  5. 理解单链表的反转(java实现)

    要求很简单,输入一个链表,反转链表后,输出新链表的表头.   反转链表是有2种方法(递归法,遍历法)实现的,面试官最爱考察的算法无非是斐波那契数列和单链表反转,递归方法实现链表反转比较优雅,但是对于不 ...

  6. javascript数据结构之单链表

    下面是用javascript实现的单链表,但是在输出的时候insert方法中存在问题,chrome的console报错说不能读取空的属性,调试了很久都没有通过,先在这里存着,以后再来修改一下. //数 ...

  7. Java数据结构之单链表

    这篇文章主要讲解了通过java实现单链表的操作,一般我们开始学习链表的时候,都是使用C语言,C语言中我们可以通过结构体来定义节点,但是在Java中,我们没有结构体,我们使用的是通过类来定义我们所需要的 ...

  8. Java数据结构-03单链表(二)

    在之前我们封装了一些操作在接口类中,并在抽象类实现了相同的方法.下面我们开始写代码: 无头结点单链表:(注意下面的AbstractList是之前抽取的类,不是java.util包下的类) public ...

  9. 图解Java数据结构之单链表

    本篇文章介绍数据结构中的单链表. 链表(Linked List)介绍 链表可分为三类: 单链表 双向链表 循环列表 下面具体分析三个链表的应用. 单链表 链表是有序的列表,它在内存中存储方式如下: 虽 ...

随机推荐

  1. 关于Array.reduce的理解与拓展

    2018年1月6日 首先我要感谢我的同事徒步上山看日出在我第一份实习的时候对我的指导,现在我也开始跟他一样开始养成写博客的习惯 现在开始讨论我遇到的第一个问题,这是我在看javascript高级程序设 ...

  2. flask 第五篇

    需求: 1. 用户名: oldboy 密码: oldboy123 2. 用户登录成功之后跳转到列表页面 3. 失败有消息提示,重新登录 4.点击学生名称之后,可以看到学生的详细信息 后端: from ...

  3. vue事件.navtive 的使用

    我们可以直接在组件标签上绑定事件了 然后在 methods 的对象中调用这个方法了 正常情况下是不可以的,但是我们可以使用事件修饰符 .navtive 就可以实现了 props的对象写法

  4. When Database Sharding is Appropriate DATABASE SHARDING

    w横切 http://www.agildata.com/database-sharding/ When Database Sharding is Appropriate Database Shardi ...

  5. Cortex-M3 双堆栈指针(MSP&PSP)

    [双堆栈指针(MSP&PSP)] Cortex-M3内核中有两个堆栈指针(MSP & PSP),但任何时刻只能使用到其中一个. 复位后处于线程模式特权级,默认使用MSP. 通过SP访问 ...

  6. 实用的60个CSS代码片段[下]

    31.有趣的& .amp { font-family: Baskerville, 'Goudy Old Style', Palatino, 'Book Antiqua', serif; fon ...

  7. JQUERY的$(function(){})和window.onload=function(){}的区别

    在Jquery里面,我们知道入口函数有两种写法:$(function(){}) 和$(document).ready(function(){}) 作用类似于传统JavaScript中的window.o ...

  8. nohup sh start.sh >/dev/null 2>&1 &

    nohup sh start.sh >/dev/null 2>&1 & 背景说明 start.sh 脚本里,写了Java应用程序启动的相关命令,并且在 log4j.prop ...

  9. [笔记] 基于nvidia/cuda的深度学习基础镜像构建流程 V0.2

    之前的[笔记] 基于nvidia/cuda的深度学习基础镜像构建流程已经Out了,以这篇为准. 基于NVidia官方的nvidia/cuda image,构建适用于Deep Learning的基础im ...

  10. gin框架教程三:JWT的使用

    JWT介绍 JWT (JSON Web Token) 是一种规范.这个规范允许我们使用JWT在用户和服务器之间安全传递信息. JWT的组成: jwt分3个部分,Header 头部.Payload 载荷 ...