导航:首页 > 编程语言 > java双向链表的实现

java双向链表的实现

发布时间:2022-06-24 21:56:28

java如何实现链表

链表是一种重要的数据结构,在程序设计中占有很重要的地位。C语言和C++语言中是用指针来实现链表结构的,由于Java语言不提供指针,所以有人认为在Java语言中不能实现链表,其实不然,Java语言比C和C++更容易实现链表结构。Java语言中的对象引用实际上是一个指针(本文中的指针均为概念上的意义,而非语言提供的数据类型),所以我们可以编写这样的类来实现链表中的结点。
class Node
{
Object data;
Node next;//指向下一个结点
}
将数据域定义成Object类是因为Object类是广义超类,任何类对象都可以给其赋值,增加了代码的通用性。为了使链表可以被访问还需要定义一个表头,表头必须包含指向第一个结点的指针和指向当前结点的指针。为了便于在链表尾部增加结点,还可以增加一指向链表尾部的指针,另外还可以用一个域来表示链表的大小,当调用者想得到链表的大小时,不必遍历整个链表。下图是这种链表的示意图:
链表的数据结构
我们可以用类List来实现链表结构,用变量Head、Tail、Length、Pointer来实现表头。存储当前结点的指针时有一定的技巧,Pointer并非存储指向当前结点的指针,而是存储指向它的前趋结点的指针,当其值为null时表示当前结点是第一个结点。那么为什么要这样做呢?这是因为当删除当前结点后仍需保证剩下的结点构成链表,如果Pointer指向当前结点,则会给操作带来很大困难。那么如何得到当前结点呢,我们定义了一个方法cursor(),返回值是指向当前结点的指针。类List还定义了一些方法来实现对链表的基本操作,通过运用这些基本操作我们可以对链表进行各种操作。例如reset()方法使第一个结点成为当前结点。insert(Object d)方法在当前结点前插入一个结点,并使其成为当前结点。remove()方法删除当前结点同时返回其内容,并使其后继结点成为当前结点,如果删除的是最后一个结点,则第一个结点变为当前结点。
链表类List的源代码如下:
import java.io.*;
public class List
{
/*用变量来实现表头*/
private Node Head=null;
private Node Tail=null;
private Node Pointer=null;
private int Length=0;
public void deleteAll()
/*清空整个链表*/
{
Head=null;
Tail=null;
Pointer=null;
Length=0;
}
public void reset()
/*链表复位,使第一个结点成为当前结点*/
{
Pointer=null;
}
public boolean isEmpty()
/*判断链表是否为空*/
{
return(Length==0);
}
public boolean isEnd()
/*判断当前结点是否为最后一个结点*/
{
if(Length==0)
throw new java.lang.NullPointerException();
else if(Length==1)
return true;
else
return(cursor()==Tail);
}
public Object nextNode()
/*返回当前结点的下一个结点的值,并使其成为当前结点*/
{
if(Length==1)
throw new java.util.NoSuchElementException();
else if(Length==0)
throw new java.lang.NullPointerException();
else
{
Node temp=cursor();
Pointer=temp;
if(temp!=Tail)
return(temp.next.data);
else
throw new java.util.NoSuchElementException();
}
}
public Object currentNode()
/*返回当前结点的值*/
{
Node temp=cursor();
return temp.data;
}

public void insert(Object d)
/*在当前结点前插入一个结点,并使其成为当前结点*/
{
Node e=new Node(d);
if(Length==0)
{
Tail=e;
Head=e;
}
else
{
Node temp=cursor();
e.next=temp;
if(Pointer==null)
Head=e;
else
Pointer.next=e;
}
Length++;
}
public int size()
/*返回链表的大小*/
{
return (Length);
}
public Object remove()
/*将当前结点移出链表,下一个结点成为当前结点,如果移出的结点是最后一个结点,则第一个结点成为当前结点*/
{
Object temp;
if(Length==0)
throw new java.util.NoSuchElementException();
else if(Length==1)
{
temp=Head.data;
deleteAll();
}
else
{
Node cur=cursor();
temp=cur.data;
if(cur==Head)
Head=cur.next;
else if(cur==Tail)
{
Pointer.next=null;
Tail=Pointer;
reset();
}
else
Pointer.next=cur.next;
Length--;
}
return temp;
}
private Node cursor()
/*返回当前结点的指针*/
{
if(Head==null)
throw new java.lang.NullPointerException();
else if(Pointer==null)
return Head;
else
return Pointer.next;
}
public static void main(String[] args)
/*链表的简单应用举例*/
{
List a=new List ();
for(int i=1;i<=10;i++)
a.insert(new Integer(i));
System.out.println(a.currentNode());
while(!a.isEnd())
System.out.println(a.nextNode());
a.reset();
while(!a.isEnd())
{
a.remove();
}
a.remove();
a.reset();
if(a.isEmpty())
System.out.println("There is no Node in List \n");
System.in.println("You can press return to quit\n");
try
{
System.in.read();
//确保用户看清程序运行结果
}
catch(IOException e)
{}
}
}
class Node
/*构成链表的结点定义*/
{
Object data;
Node next;
Node(Object d)
{
data=d;
next=null;
}
}
读者还可以根据实际需要定义新的方法来对链表进行操作。双向链表可以用类似的方法实现只是结点的类增加了一个指向前趋结点的指针。
可以用这样的代码来实现:
class Node
{
Object data;
Node next;
Node previous;
Node(Object d)
{
data=d;
next=null;
previous=null;
}
}
当然,双向链表基本操作的实现略有不同。链表和双向链表的实现方法,也可以用在堆栈和队列的实现中,这里就不再多写了,有兴趣的读者可以将List类的代码稍加改动即可。

希望对你有帮助。

⑵ 用JAVA语言,编写一个链表类(双向链表),实现插入,删除,查找操作。新手,要俗易懂些,最好自己调适通过。急

定义接口:
//Deque.java
package dsa; //根据自己的程序位置不同

public interface Deque {
public int getSize();//返回队列中元素数目
public boolean isEmpty();//判断队列是否为空
public Object first() throws ExceptionQueueEmpty;//取首元素(但不删除)
public Object last() throws ExceptionQueueEmpty;//取末元素(但不删除)
public void insertFirst(Object obj);//将新元素作为首元素插入
public void insertLast(Object obj);//将新元素作为末元素插入
public Object removeFirst() throws ExceptionQueueEmpty;//删除首元素
public Object removeLast() throws ExceptionQueueEmpty;//删除末元素
public void Traversal();//遍历
}

双向链表实现:
//Deque_DLNode.java
/*
* 基于双向链表实现双端队列结构
*/

package dsa;

public class Deque_DLNode implements Deque {
protected DLNode header;//指向头节点(哨兵)
protected DLNode trailer;//指向尾节点(哨兵)
protected int size;//队列中元素的数目

//构造函数
public Deque_DLNode() {
header = new DLNode();
trailer = new DLNode();
header.setNext(trailer);
trailer.setPrev(header);
size = 0;
}

//返回队列中元素数目
public int getSize()
{ return size; }

//判断队列是否为空
public boolean isEmpty()
{ return (0 == size) ? true : false; }

//取首元素(但不删除)
public Object first() throws ExceptionQueueEmpty {
if (isEmpty())
throw new ExceptionQueueEmpty("意外:双端队列为空");
return header.getNext().getElem();
}

//取末元素(但不删除)
public Object last() throws ExceptionQueueEmpty {
if (isEmpty())
throw new ExceptionQueueEmpty("意外:双端队列为空");
return trailer.getPrev().getElem();
}

//在队列前端插入新节点
public void insertFirst(Object obj) {
DLNode second = header.getNext();
DLNode first = new DLNode(obj, header, second);
second.setPrev(first);
header.setNext(first);
size++;
}

//在队列后端插入新节点
public void insertLast(Object obj) {
DLNode second = trailer.getPrev();
DLNode first = new DLNode(obj, second, trailer);
second.setNext(first);
trailer.setPrev(first);
size++;
}

//删除首节点
public Object removeFirst() throws ExceptionQueueEmpty {
if (isEmpty())
throw new ExceptionQueueEmpty("意外:双端队列为空");
DLNode first = header.getNext();
DLNode second = first.getNext();
Object obj = first.getElem();
header.setNext(second);
second.setPrev(header);
size--;
return(obj);
}

//删除末节点
public Object removeLast() throws ExceptionQueueEmpty {
if (isEmpty())
throw new ExceptionQueueEmpty("意外:双端队列为空");
DLNode first = trailer.getPrev();
DLNode second = first.getPrev();
Object obj = first.getElem();
trailer.setPrev(second);
second.setNext(trailer);
size--;
return(obj);
}

//遍历
public void Traversal() {
DLNode p = header.getNext();
while (p != trailer) {
System.out.print(p.getElem()+" ");
p = p.getNext();
}
System.out.println();
}
}

⑶ 双向循环链表java

我们也做这个,,你是是吧
package KeCheng1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Scanner;

//定义节点类
class Node<AnyType> {
public AnyType data;
public Node<AnyType> prev;
public Node<AnyType> next;
public Node(AnyType d,Node<AnyType> p,Node<AnyType> n){
data=d;
prev=p;
next=n;}}
public class MyLinkedList<AnyType> {
private int theSize;
private Node<AnyType> beginMarker; //头标记或头节点
private Node<AnyType> endMarker; //尾标记或尾节点
public MyLinkedList(){
beginMarker=new Node<AnyType>(null,endMarker,endMarker);
endMarker = new Node<AnyType>(null,beginMarker,beginMarker);
beginMarker.next = endMarker;
theSize = 0;}
public int size(){
return theSize;}
public boolean add(AnyType x){
add(size(),x);
return true;}
public void add(int idx,AnyType x){
Node<AnyType> p;
p=getNode(idx);
addBefore(p,x);}
private Node<AnyType> getNode(int idx) {
Node<AnyType> p;
if( idx < 0 || idx > size( ) )
throw new IndexOutOfBoundsException( );
if( idx < size( ) / 2 ) {
p = beginMarker.next;
for( int i = 0; i < idx; i++ )
p = p.next;}
else
{ p = endMarker;
for( int i = size( ); i > idx; i-- )
p = p.prev; }
return p;}
private void addBefore( Node<AnyType> p, AnyType x ) {
Node<AnyType> newNode = new Node<AnyType>( x, p.prev, p );
newNode.prev.next = newNode;
p.prev = newNode;
theSize++;}
public AnyType remove( int idx ){
return remove( getNode(idx));}
private AnyType remove(Node<AnyType> p){
p.next.prev = p.prev;
p.prev.next = p.next;
theSize--;
return p.data;}

public void print(){//输出链表
for(Node<AnyType>x=beginMarker.next;x.next!=beginMarker;x=x.next)
System.out.print(x.data+" ");
System.out.print("\n");}
public AnyType get( int idx ){
return getNode( idx ).data; }

public static void main(String[] args){
MyLinkedList<Integer> La = new MyLinkedList<Integer>();
int Length;
Scanner sc = new Scanner(System.in);
System.out.println("请输入要创建的双向链表的长度:(大于6)");
Length = sc.nextInt();
System.out.println("请输入"+Length+"个元素创建La双向链表:");
for(int i=0;i<Length;i++)
{La.add(sc.nextInt());}
System.out.println("输入的原La双向链表:");
La.print();
System.out.println("在双向链表的第3个位置插入20:");
La.add(3,20);
La.print();
System.out.println("删除第五位置上的数:");
La.remove(5);
La.print();
System.out.println("插入最后一个节点:99");
La.add(Length,99);
La.print();
System.out.println("插入第一个节点0:");
La.add(0,0);
La.print();
System.out.println("就地逆置:");
int M=Length+2;
int b=0;
for(Length=Length+1;Length>=0;Length--){
int a=La.get(M-1);
La.add(b,a);
b=b+1;
La.remove(M);
}
La.print();
}
}

⑷ java数据结构--实现双链表

调换了出了什么问题了吗?调换后应该结果不变的。你的循环有问题的p.next != null第一个节点却是ew Node(e,null,null); 明显下个的节点就是null啊,这样写永远都只有一个节点的。

⑸ 如何实现Java中一个简单的LinkedList

与实现ArrayList的名字一样,为SimpleLinkedList。源码地址,欢迎star,fork
构建一个双向链表
构建的代码如下:
?

1
2
3
4
5
6
7
8
9
10

private static class Node<E>{
E item;
Node<E> next;
Node<E> prev;
public Node(E item, Node<E> next, Node<E> prev) {
this.item = item;
this.next = next;
this.prev = prev;
}
}

常规的双向链表的构建方法,一个数字域存放数组,一个前指针指向一个Node类型的元素,一个后指针指向一个Node类型的元素。
对于LinkedList的实现而言,还需要以下三个成员变量
?

⑹ java 中如何实现链表操作

class Node {
Object data;
Node next;//申明类Node类的对象叫Next

public Node(Object data) { //类Node的构造函数
setData(data);
}
public void setData(Object data) {
this.data = data;
}
public Object getData() {
return data;
}
}

class Link {
Node head;//申明一个Node类的一个对象 head
int size = 0;

public void add(Object data) {
Node n = new Node(data); //调用Node类的构造函数

链表是一种重要的数据结构,在程序设计中占有很重要的地位。C语言和C++语

言中是用指针来实现链表结构的,由于Java语言不提供指针,所以有人认为在

Java语言中不能实现链表,其实不然,Java语言比C和C++更容易实现链表结构

。Java语言中的对象引用实际上是一个指针(本文中的指针均为概念上的意义,

而非语言提供的数据类型),所以我们可以编写这样的类来实现链表中的结点。

class Node
{
Object data;
Node next;//指向下一个结点
}

将数据域定义成Object类是因为Object类是广义超类,任何类对象都可以给

其赋值,增加了代码的通用性。为了使链表可以被访问还需要定义一个表头,表

头必须包含指向第一个结点的指针和指向当前结点的指针。为了便于在链表尾部

增加结点,还可以增加一指向链表尾部的指针,另外还可以用一个域来表示链表

的大小,当调用者想得到链表的大小时,不必遍历整个链表。下图是这种链表的

示意图:

链表的数据结构

我们可以用类List来实现链表结构,用变量Head、Tail、Length、Pointer

来实现表头。存储当前结点的指针时有一定的技巧, Pointer并非存储指向当前

结点的指针,而是存储指向它的前趋结点的指针,当其值为null时表示当前结点是

第一个结点。那么为什么要这样做呢?这是因为当删除当前结点后仍需保证剩下

的结点构成链表,如果Pointer指向当前结点,则会给操作带来很大困难。那么如

何得到当前结点呢,我们定义了一个方法cursor(),返回值是指向当前结点的指

针。类List还定义了一些方法来实现对链表的基本操作,通过运用这些基本操作

我们可以对链表进行各种操作。例如reset()方法使第一个结点成为当前结点。

insert(Object d)方法在当前结点前插入一个结点,并使其成为当前结点。

remove()方法删除当前结点同时返回其内容,并使其后继结点成为当前结点,如

果删除的是最 后一个结点,则第一个结点变为当前结点。

链表类List的源代码如下:

import java.io.*;
public class List
{
/*用变量来实现表头*/
private Node Head=null;
private Node Tail=null;
private Node Pointer=null;
private int Length=0;
public void deleteAll()
/*清空整个链表*/
{
Head=null;
Tail=null;
Pointer=null;
Length=0;
}
public void reset()
/*链表复位,使第一个结点成为当前结点*/
{
Pointer=null;
}
public boolean isEmpty()
/*判断链表是否为空*/
{
return(Length==0);
}
public boolean isEnd()
/*判断当前结点是否为最后一个结点*/
{
if(Length==0)
throw new java.lang.NullPointerException();
else if(Length==1)
return true;
else
return(cursor()==Tail);
}
public Object nextNode()
/*返回当前结点的下一个结点的值,并使其成为当前结点*/
{
if(Length==1)
throw new java.util.NoSuchElementException();
else if(Length==0)
throw new java.lang.NullPointerException();
else
{
Node temp=cursor();
Pointer=temp;
if(temp!=Tail)
return(temp.next.data);
else
throw new java.util.NoSuchElementException();
}
}
public Object currentNode()
/*返回当前结点的值*/
{
Node temp=cursor();
return temp.data;
}

public void insert(Object d)
/*在当前结点前插入一个结点,并使其成为当前结点*/
{
Node e=new Node(d);
if(Length==0)
{
Tail=e;
Head=e;
}
else
{
Node temp=cursor();
e.next=temp;
if(Pointer==null)
Head=e;
else
Pointer.next=e;
}
Length++;
}
public int size()
/*返回链表的大小*/
{
return (Length);
}
public Object remove()
/*将当前结点移出链表,下一个结点成为当前结点,如果移出的结点是最后

一个结点,则第一个结点成为当前结点*/
{
Object temp;
if(Length==0)
throw new java.util.NoSuchElementException();
else if(Length==1)
{
temp=Head.data;
deleteAll();
}
else
{
Node cur=cursor();
temp=cur.data;
if(cur==Head)
Head=cur.next;
else if(cur==Tail)
{
Pointer.next=null;
Tail=Pointer;
reset();
}
else
Pointer.next=cur.next;
Length--;
}
return temp;
}
private Node cursor()
/*返回当前结点的指针*/
{
if(Head==null)
throw new java.lang.NullPointerException();
else if(Pointer==null)
return Head;
else
return Pointer.next;
}
public static void main(String[] args)
/*链表的简单应用举例*/
{
List a=new List ();
for(int i=1;i<=10;i++)
a.insert(new Integer(i));
System.out.println(a.currentNode());
while(!a.isEnd())
System.out.println(a.nextNode());
a.reset();
while(!a.isEnd())
{
a.remove();
}
a.remove();
a.reset();
if(a.isEmpty())
System.out.println("There is no Node in List \n");
System.in.println("You can press return to quit\n");
try
{
System.in.read();
//确保用户看清程序运行结果
}
catch(IOException e)
{}
}
}
class Node
/*构成链表的结点定义*/
{
Object data;
Node next;
Node(Object d)
{
data=d;
next=null;
}
}

读者还可以根据实际需要定义新的方法来对链表进行操作。双向链表可以用

类似的方法实现只是结点的类增加了一个指向前趋结点的指针。

可以用这样的代码来实现:

class Node
{
Object data;
Node next;
Node previous;
Node(Object d)
{
data=d;
next=null;
previous=null;
}
}

当然,双向链表基本操作的实现略有不同。链表和双向链表的实现方法,也

可以用在堆栈和队列的实现中,这里就不再多写了,有兴趣的读者可以将List类

的代码稍加改动即可。

⑺ 谁能帮我把这Java单向链表改成双向链表

一、JAVA单向链表的操作(增加节点、查找节点、删除节点)

classLink{//链表类
classNode{//保存每一个节点,此处为了方便直接定义成内部类
privateStringdata;//节点的内容
privateNodenext;//保存下一个节点

publicNode(Stringdata){//通过构造方法设置节点内容
this.data=data;
}

publicvoidadd(Nodenode){//增加节点
if(this.next==null){//如果下一个节点为空,则把新节点加入到next的位置上
this.next=node;
}else{//如果下一个节点不为空,则继续找next
this.next.add(node);
}
}

publicvoidprint(){//打印节点
if(this.next!=null){
System.out.print(this.data+"-->");
this.next.print();
}else{
System.out.print(this.data+" ");
}
}

publicbooleansearch(Stringdata){//内部搜索节点的方法
if(this.data.equals(data)){
returntrue;
}
if(this.next!=null){
returnthis.next.search(data);
}else{
returnfalse;
}
}

publicvoiddelete(Nodeprevious,Stringdata){//内部删除节点的方法
if(this.data.equals(data)){
previous.next=this.next;
}else{
if(this.next!=null){
this.next.delete(this,data);
}
}
}
}

privateNoderoot;//定义头节点

publicvoidaddNode(Stringdata){//根据内容添加节点
NodenewNode=newNode(data);//要插入的节点
if(this.root==null){//没有头节点,则要插入的节点为头节点
this.root=newNode;
}else{//如果有头节点,则调用节点类的方法自动增加
this.root.add(newNode);
}
}

publicvoidprint(){//展示列表的方法
if(root!=null){//当链表存在节点的时候进行展示
this.root.print();
}
}

publicbooleansearchNode(Stringdata){//在链表中寻找指定内容的节点
returnroot.search(data);//调用内部搜索节点的方法
}

publicvoiddeleteNode(Stringdata){//在链表中删除指定内容的节点
if(root.data.equals(data)){//如果是头节点
if(root.next!=null){
root=root.next;
}else{
root=null;
}
}else{
root.next.delete(this.root,data);
}
}
}

二、双向链表的简单实现

publicclassDoubleLink<T>{

/**
*Node<AnyType>类定义了双向链表中节点的结构,它是一个私有类,而其属性和构造函数都是公有的,这样,其父类可以直接访问其属性
*而外部类根本不知道Node类的存在。
*
*@authorZHB
*
*@param<T>
*类型
*@paramData
*是节点中的数据
*@parampre
*指向前一个Node节点
*@paramnext
*指向后一个Node节点
*/
privateclassNode<T>{
publicNode<T>pre;
publicNode<T>next;
publicTdata;

publicNode(Tdata,Node<T>pre,Node<T>next){
this.data=data;
this.pre=pre;
this.next=next;
}

publicNode(){
this.data=null;
this.pre=null;
this.next=null;
}
}

//下面是DoubleLinkedList类的数据成员和方法
privateinttheSize;
privateNode<T>Header;
privateNode<T>Tail;

/*
*构造函数我们构造了一个带有头、尾节点的双向链表头节点的Next指向尾节点为节点的pre指向头节点链表长度起始为0。
*/
publicDoubleLink(){

theSize=0;
Header=newNode<T>(null,null,null);
Tail=newNode<T>(null,Header,null);

Header.next=Tail;
}

publicvoidadd(Titem){

Node<T>aNode=newNode<T>(item,null,null);

Tail.pre.next=aNode;
aNode.pre=Tail.pre;
aNode.next=Tail;
Tail.pre=aNode;

theSize++;
}

publicbooleanisEmpty(){
return(this.theSize==0);
}

publicintsize(){
returnthis.theSize;
}

publicTgetInt(intindex){

if(index>this.theSize-1||index<0)
();

Node<T>current=Header.next;

for(inti=0;i<index;i++){
current=current.next;
}

returncurrent.data;
}

publicvoidprint(){

Node<T>current=Header.next;

while(current.next!=null){

System.out.println(current.data.toString());

current=current.next;
}

}

publicstaticvoidmain(String[]args){
DoubleLink<String>dLink=newDoubleLink<String>();

dLink.add("zhb");
dLink.add("zzb");
dLink.add("zmy");
dLink.add("zzj");

System.out.println("size:"+dLink.size());
System.out.println("isEmpty?:"+dLink.isEmpty());
System.out.println("3:"+dLink.getInt(2));
dLink.print();
}
}

⑻ java怎么用链表实现

在数据结构中经常看见的一个基本概念-链表。
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
在Java中,对于链表的实现都是基于引用数据类型操作的。实现大致如下:
定义节点类Node,节点的概念很重要,一个链表是由各各节点连接在一起组成的。在节点类Node中定义节点内容及指向下一节点的引用,再增加一个添加节点的方法即可完成链表实现。
链表有很多种不同的类型:单向链表,双向链表以及循环链表。在执行效率上,相比数组而言,链表插入快查找慢,开发中得根据实际业务使用。

阅读全文

与java双向链表的实现相关的资料

热点内容
压缩机每次启动12分钟就停 浏览:729
creo复制曲面命令 浏览:959
程序员恋上女硕士 浏览:668
ansys的get命令 浏览:987
国外dns苹果服务器地址 浏览:430
国家职业技术资格证书程序员 浏览:652
奇瑞租车app是什么 浏览:98
系统源码安装说明 浏览:420
命令行加壳 浏览:96
解压时显示防失效视频已加密 浏览:295
苹果短信加密发送 浏览:446
天翼私有云服务器租用 浏览:733
贵州云服务器属于哪个上市公司 浏览:58
编程联动教程 浏览:481
小天才app怎么升级v242 浏览:545
简单手工解压玩具制作大全 浏览:928
免费编程电子书 浏览:870
想玩游戏什么app最合适 浏览:560
安卓手机如何用airportspro 浏览:449
怎么清理idea编译缓存 浏览:952