一、单链表基本概念

单链表是一种链式存取的数据结构,用一组地址任意的存储单元(一般是非连续存储单元)存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素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. Selenium 的页面加载以及几种等待的问题

    1. PageLoadStrategy : 当调用driver.get("https://xxxx.xxx.xxx")来访问某页面时,get方法通常会阻塞浏览器直到页面完全加载后才 ...

  2. pytype

    与mypy相比不仅可以显示错误行数,还可以看到哪个函数错误. mypy的图 pytype的图

  3. koa 基础(三)路由的另一种写法

    1.配置路由 app.js // 引入模块 const Koa = require('koa'); const router = require('koa-router')(); /*引入是实例化路由 ...

  4. 创建DevExtreme应用程序

    如果你从头开始一个项目,那就使用DevExtreme Angular 模板.生成的项目带导航菜单以及在响应布局中的几个对应的示例视图. 你可以使用 DevExtreme CLI 生成应用程序: npx ...

  5. koa2环境搭建

    npm install -g koa-generator koa2 ssy-koa2 cd ssy-koa2 npm install

  6. LC 712. Minimum ASCII Delete Sum for Two Strings

    Given two strings s1, s2, find the lowest ASCII sum of deleted characters to make two strings equal. ...

  7. GitHub-Microsoft:DotNet3

    ylbtech-GitHub-Microsoft:DotNet3 1.返回顶部 · mbmlbook Sample code for the Model-Based Machine Learning ...

  8. web搜索框的制作(必应)

    搜索框中我们输入一些字或者字母,为何下面就会有一些自动补齐的相关搜索,比如我在搜索输入框中输入一个字母e,下面就会出现饿了么,e租宝,ems等相关的搜索链接.然后经过百度,发现原来很多厂商的服务器早已 ...

  9. tensorflow二进制文件读取与tfrecords文件读取

    1.知识点 """ TFRecords介绍: TFRecords是Tensorflow设计的一种内置文件格式,是一种二进制文件,它能更好的利用内存, 更方便复制和移动,为 ...

  10. Prism框架 如何在主程序中合理的弹出子窗体

    说起子窗体,大家都会想到ChildWindow,多熟悉的一个控件.不错,Sliverlight中已经提供了子窗体的具体实现,而在WPF中却没有这么好的事情(有的第三方控件商已经提供此控件).最常见的实 ...