java實現雙向鏈表
① 用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語言沒有指針,怎樣實現鏈表
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的源代碼如下:
package cn.javatx; import java.io.IOException;/**
* @author ljfan
*
*/
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.out.println("You can press return to quitn");
try {
System.in.read();
} catch (IOException e) {
}
}
}class Node {
Object data;
Node next;Node(Object d) {
data = d;
next = null;
}
}
當然,雙向鏈表基本操作的實現略有不同。鏈表和雙向鏈表的實現方法,也可以用在堆棧和隊列的實現中
③ 怎麼改為雙向鏈表
具體是使用什麼語言來實現呢?如果是用C/C++或JAVA語言的話,可以通過在單向鏈表節點添加數據域和指針域的方法來使單向鏈表變成雙向鏈表。每一個鏈表節點的數據域指向下一個鏈表前節點的指針域,前節點的指針域指向後節點的數據域,這樣循環往復就構成了一個雙向鏈表。
④ 雙向循環鏈表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 單向鏈表 雙向鏈表
看看
http://www..com/s?bs=v&f=8&wd=JAVA+%B5%A5%CF%F2%C1%B4%B1%ED+%CB%AB%CF%F2%C1%B4%B1%ED
//雙向鏈表的簡單表達
public class Mulit {
private class Node
{
private String data;
private Node upNode;
private Node downNode;
public Node()
{
data=null;
upNode=null;
downNode=null;
}
public Node(String newData,Node newDownNode)
{
data=newData;
downNode=newDownNode;
// upNode=newDownNode;
}
}
Node head;
public Mulit()
{
head=null;
}
public void add(String newData)
{
Node lastNode=head;
if(head==null)
head=new Node(newData,head);
else
{
head=new Node(newData,head);
lastNode.upNode=head;
}
}
public void display()
{
Node position =head;
while(position!=null)
{
System.out.print(position.data);
position=position.downNode;
}
}
public void otherDisp()
{
Node position=head;
while(position.downNode!=null)
{
position=position.downNode;
}
//現實的時候有顯示不了最後一個,需要解決
do
{
System.out.print(position.data);
position=position.upNode;
}
while(position.upNode!=null);
}
public static void main (String[] args)
{
Mulit m=new Mulit();
m.add("hello");
m.add("world");
m.add("!");
m.add("");
m.display();
System.out.println();
m.otherDisp();
}
}
生成輸出:
--------------------配置: <--------------------
!worldhello
helloworld!
處理已完成。
⑥ java 什麼是單向鏈表 和 雙向鏈表
鏈表是類似一種數據結構的東西,就是分別存放有地址以及數據單項鏈表一般是上一個存放地址的地方存放下一個節點的地址,而雙向的就是有兩個存放地址的地方,分別存上一個以及下一個的地址。大概是這樣子
⑦ 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如何創建一個單鏈表和雙鏈表
單向鏈表
單向鏈表就是通過每個結點的指針指向下一個結點從而鏈接起來的結構。
單向鏈表的初始化:這里我所講的鏈表都是頭結點不參與計算的,也就是說第一個結點都是頭結點後面的第一個結點。所以我要先申明一點,這里我把鏈表的初始化放在了構造函數部分,然後析構函數負責釋放頭結點的內存。
單向鏈表的創建過程:鏈表的創建就是添加結點到鏈表的最後,開始是添加一個結點到head結點後面,然後添加一個結點到上次添加的結點後面,每次新建的結點的指針總是指向NULL指針。從上面的示意圖可以看出,我們需要一個輔助指針一直指向最後一個結點,這個輔助結點就是為了讓每次添加的結點都放置在最後一個位置。
單向鏈表插入結點過程:源代碼中的的插入結點函數我設置了一個指定位置,就是在指定位置插入結點。首先,通過位置變數position讓ptemp結點移動到要插入位置的前一個位置,然後接下來的過程就是和創建鏈表的過程是一樣的,把新建的結點添加到ptemp的後面。這里變數position可以從1到鏈表長度加1,意思就是如果不算頭結點的話有3個結點,那你的position變數就可以從1到4,這是因為ptemp指針可以到第3個結點的位置,所以新建結點的位置就可以到4了。
單向鏈表刪除結點過程:源代碼中的刪除結點函數也有一個指定位置變數,為了刪除指定位置的結點。和插入結點一樣通過變數position把ptemp移動到要刪除結點的前一個位置,然後讓ptemp結點中的指針指向要刪除結點後面的一個結點,也就是ptemp結點的下一個的下一個結點,雖然這個結點可能為空,但是程序還是正常運行。但是這里和插入結點不同的是變數position只能從1到鏈表的長度,是因為ptemp移動到最後一個結點的時候,它的下一個結點為空,所以不不需要參與刪除了。
雙向鏈表
1.聽名字可能就能猜到雙向鏈表就是鏈表結點包含兩個指針,一個指針是指向下一個結點的,另一個指針當然就是指向上一個結點的。
2.雙向鏈表的初始化:由於這里的鏈表頭結點不參與計算,所以頭結點的pPre指針是一直指向NULL指針的。
3.雙向鏈表的創建過程:由於雙向鏈表的每個結點包含兩個指針那麼這個時候我們就要小心處理好每一個指針的指向,要不然會有很多意想不到的錯誤。同樣的,和單向鏈表的創建過程一樣,需要一個輔助指針來指向最後一個結點,然後每新建一個結點,這個結點的pNext指針都是指向NULL指針的,pPre指針指向上一個結點(這是和單向鏈表不同的地方),然後讓上一個指針的pNext指向新建的結點,這樣整個鏈表就連接起來了。
4.雙向鏈表插入結點過程:知道了雙向鏈表的創建過程,那麼插入結點的過程就大同小異 了,有一點需要特別注意的就是這里的變數position范圍也是從1到鏈表長度加1,但是如果待插入的位置是最後一個位置的話,情況就不同了,看到下面的圖我們可以很好的理解,因為沒新建一個結點的時候都需要處理兩個指針,而且新建結點的下一個結點的pPre指針就需要指向這個新建的結點,但是有可能這個新建的結點可能就已經是最後一個結點了,那麼這個時候再執行
ptemp->pNext->pPre=pnew;
這條指令的時候就會報錯了,因為ptemp->pNext已經是個NULL指針了,那空指針哪裡還有pPre呢。因此在程序中要進行一次判斷,看看結點是否是最後一個結點。
5.雙向鏈表刪除結點的過程:要注意的問題和插入結點一樣,看看這個結點是否為NULL。這里就不重復了。
⑨ java中 雙向鏈表是什麼意思啊,是用來幹啥的啊,求大神解答謝謝
採用雙向循環鏈表作為數據結構
1 新元素的下一個指向header
2 新元素的上一個指向header的上一個
3 新元素的上一個的下一個指向新元素
4 新元素的下一個的上一個指向新元素
一般LinkedList是採用雙向循環鏈表,無需擴容,添加元素添加到最後即可
⑩ java,數據結構雙向鏈表問題
其實 newLink.next = null 可以不寫的 因為 Link newLink = new Link(dd) 這樣的newLink.next 就是null
我看了下源代碼,在insertAfter中寫明是為了和當前插入的元素是在鏈表的最後一位還是在中間插入,這樣是的話newLink.next的值是不同的
if (current == last) // if last link,
{
newLink.next = null; //可以不寫的 ,new出來的就是空。目的是與else的區分
else{
newLink.next = current.next;
}