1. java單鏈表中結點類用private修飾,怎麼用在鏈表類里
在Java單鏈表中,節點類通常包含兩個屬性:一個存儲數據的變數和一個指向下一個節點談兄皮的變數。為了保證數據的封裝性,通常會將這兩個屬性都用private修飾,然後提供對應的getter和setter方法含差來訪問和修改這些屬性。
下面是一個簡單的Java單鏈表節點類示例:
public class ListNode {
private int val;
private ListNode next;
public ListNode(int val) {
this.val = val;
}
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
public ListNode getNext() {
return next;
}
public void setNext(ListNode next) {
this.next = next;
}
}
在鏈表類中,我們需要創建一個頭節點來表示整個鏈表的起始位置。可以將鏈表類的定義如下:
public class LinkedList {
private ListNode head;
public LinkedList() {
this.head = null;
}
// 添加節點到鏈表尾部
public void addNode(int val) {
ListNode newNode = new ListNode(val);
if (head == null) {
head = newNode;
} else {
ListNode cur = head;
while (cur.getNext() != null) {
cur = cur.getNext();
}
cur.setNext(newNode);
}
}
// 遍歷鏈表並輸出節點值
public void traverse() {
ListNode cur = head;
while (cur != null) {
System.out.print(cur.getVal() + " ");
cur = cur.getNext();
}
System.out.println();
}
}
在鏈表類中,我們將head屬性也用private修飾,並提供對應的getter和setter方法來訪問和修改head屬性。在addNode方法中,我們首先判斷鏈表是否為空,如果為空,直接將新節點作為頭節點;否則,遍歷鏈表找到尾節點並將新節點接在其後面。在traverse方法中,我們遍歷整個鏈表並輸出每個節點的值。
使用時,可以創建一個新的LinkedList對象,然後調用其addNode方法添加節點,最後調塵和用traverse方法遍歷鏈表並輸出每個節點的值。例如:
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.addNode(1);
list.addNode(2);
list.addNode(3);
list.traverse();
}
這段代碼會輸出:1 2 3。
2. java怎麼用鏈表實現
在數據結構中經常看見的一個基本概念-鏈表。
鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。
在Java中,對於鏈表的實現都是基於引用數據類型操作的。實現大致如下:
定義節點類Node,節點的概念很重要,一個鏈表是由各各節點連接在一起組成的。在節點類Node中定義節點內容及指向下一節點的引用,再增加一個添加節點的方法即可完成鏈表實現。
鏈表有很多種不同的類型:單向鏈表,雙向鏈表以及循環鏈表。在執行效率上,相比數組而言,鏈表插入快查找慢,開發中得根據實際業務使用。
3. Java語言沒有指針,怎樣實現鏈表
Java語言中的對象引用實際上是一個指針(這里的指針均為概念上的意義,而非語言提供的數據類型),所以我們可以編寫這樣的類來實現鏈表中的結點。
程序代碼:
classNode
{
Objectdata;
Nodenext;//指向下一個結點
}
將數據域定義成Object類是因為Object類是廣義超類,任何類對象都可以給其賦值,增加了代碼的通用性。為了使鏈表可以被訪問還需要定義一個表頭,表頭必須包含指向第一個結點的指針和指向當前結點的指針。為了便於在鏈表尾部增加結點,還可以增加一指向鏈表尾部的指針,另外還可以用一個域來表示鏈表的大小,當調用者想得到鏈表的大小時,不必遍歷整個鏈表。
鏈表的數據結構我們可以用類List來實現鏈表結構,用變數Head、Tail、Length、Pointer來實現表頭。存儲當前結點的指針時有一定的技巧,Pointer並非存儲指向當前結點的指針,而是存儲指向它的前趨結點的指針,當其值為null時表示當前結點是第一個結點,因為當刪除當前結點後仍需保證剩下的結點構成鏈表,如果Pointer指向當前結點,則會給操作帶來很大困難。如何得到當前結點呢?我們定義了一個方法cursor(),返回值是指向當前結點的指針。類List還定義了一些方法來實現對鏈表的基本操作,通過運用這些基本操作我們可以對鏈表進行各種操作。例如reset()方法使第一個結點成為當前結點。insert(Object d)方法在當前結點前插入一個結點,並使其成為當前結點。remove()方法刪除當前結點同時返回其內容,並使其後繼結點成為當前結點,如果刪除的是最後一個結點,則第一個結點變為當前結點。
鏈表類List的源代碼如下:
packagecn.javatx;importjava.io.IOException;/**
*@authorljfan
*
*/
publicclassList{
privateNodeHead=null;
privateNodeTail=null;
privateNodePointer=null;
privateintLength=0;publicvoiddeleteAll(){
Head=null;
Tail=null;
Pointer=null;
Length=0;
}publicvoidreset(){
Pointer=null;
}publicbooleanisEmpty(){
return(Length==0);
}publicbooleanisEnd(){
if(Length==0)
thrownewjava.lang.NullPointerException();
elseif(Length==1)
returntrue;
else
return(cursor()==Tail);
}publicObjectnextNode(){
if(Length==1)
thrownewjava.util.NoSuchElementException();
elseif(Length==0)
thrownewjava.lang.NullPointerException();
else{
Nodetemp=cursor();
Pointer=temp;
if(temp!=Tail)
return(temp.next.data);
else
thrownewjava.util.NoSuchElementException();
}
}publicObjectcurrentNode(){
Nodetemp=cursor();
returntemp.data;
}publicvoidinsert(Objectd){
Nodee=newNode(d);
if(Length==0){
Tail=e;
Head=e;
}else{
Nodetemp=cursor();
e.next=temp;
if(Pointer==null)
Head=e;
else
Pointer.next=e;
}
Length++;
}publicintsize(){
return(Length);
}publicObjectremove(){
Objecttemp;
if(Length==0)
thrownewjava.util.NoSuchElementException();
elseif(Length==1){
temp=Head.data;
deleteAll();
}else{
Nodecur=cursor();
temp=cur.data;
if(cur==Head)
Head=cur.next;
elseif(cur==Tail){
Pointer.next=null;
Tail=Pointer;
reset();
}else
Pointer.next=cur.next;
Length--;
}
returntemp;
}privateNodecursor(){
if(Head==null)
thrownewjava.lang.NullPointerException();
elseif(Pointer==null)
returnHead;
else
returnPointer.next;
}publicstaticvoidmain(String[]args){
Lista=newList();
for(inti=1;i<=10;i++)
a.insert(newInteger(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("ThereisnoNodeinListn");
System.out.println("Youcanpressreturntoquitn");
try{
System.in.read();
}catch(IOExceptione){
}
}
}classNode{
Objectdata;
Nodenext;Node(Objectd){
data=d;
next=null;
}
}
當然,雙向鏈表基本操作的實現略有不同。鏈表和雙向鏈表的實現方法,也可以用在堆棧和隊列的現實中。
4. Java鏈表ListNode的理解與操作技巧
深入理解Java鏈表——ListNode的奧秘與高效操作
鏈表,這位數據結構的低調明星,與數組並肩存在,但實現原理卻大相徑庭。Java中,ArrayList依託數組,而LinkedList則依託鏈表。鏈表的一大優勢在於數據的動態添加和刪除,但循環遍歷效率卻不如數組。它是一個由節點(Node)串聯而成的線性結構,內存中的數據分布不連續,每個節點持有自己的數據和對下一個節點的引用,形成了鏈式連接。鏈表的主角——單向鏈表,僅有一個頭節點(Head),所有的操作都是通過它進行的,無論是插入還是刪除。
想像一下,就像一個看不見的線索,每個節點都持有指向下一個節點的線索,上圖中,頭節點就像這個鏈條的起點。有趣的是,添加節點的過程卻從鏈尾開始,新節點被插入到當前尾節點之後,形成一個不斷擴展的序列。每個節點都僅知道自己下一個節點的位置,這就是鏈表的魅力所在。
節點的構造精巧,由對象值(val或data)和指向下一個節點的引用(Node.next)構成,就像一個信息傳遞的接力賽,每個節點都承載著數據和傳遞的使命。以下是ListNode的精簡版定義:
在MyList類中,鏈表的操作方法更是精細入微。添加節點(add)、刪除指定節點(delete)、獲取節點長度(size)、查找節點位置(find),以及通過下標獲取節點(get),每個方法都展示了鏈表操作的靈活性和高效性。比如,delete方法通過遍歷鏈表找到目標節點,然後更新節點連接,避免了數組需要移動大量元素的麻煩。
最後,別忘了鏈表還有個華麗轉身的時刻——鏈表反轉(reverse)。通過交換每個節點的前後節點,鏈表從頭到尾的順序來了個180度的大轉彎,展示了鏈表操作的多樣性和可能性。
鏈表,這個看似平凡的數據結構,實則蘊含著豐富的操作技巧和靈活性。通過熟練掌握ListNode,你將能在Java編程世界中游刃有餘地處理各種數據操作,讓代碼更加高效且優雅。
5. 用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();
}
}
6. Java中ArrayList、LinkedList、Vector、Stack的比較
一、介紹
在Java中,ArrayList、LinkedList、Vector和Stack都是List介面的實現類。它們各自有獨特的特性和性能特點。
ArrayList基於動態數組實現,提供快速的隨機訪問,但插入和刪除操作效率較低。
LinkedList採用雙向鏈表結構,適合進行插入和刪除操作,但隨機訪問效率較低。
Vector類似於ArrayList,但實現了線程安全,因此在多線程環境中有較好的表現,但性能不如ArrayList。
Stack繼承自Vector,遵循先進後出原則(FILO)。
二、性能測試與分析
通過性能測試,可以看出不同類在讀取、插入和刪除操作上的效率差異。
讀取操作:ArrayList > Vector > Stack > LinkedList
插入操作:LinkedList > Vector > ArrayList > Stack
刪除操作:LinkedList > Vector > ArrayList > Stack
三、插入操作分析
在插入元素時,LinkedList需在鏈表中查找指定位置並插入新節點,而ArrayList則通過復制部分數組來實現,Vector也採用類似方式。
四、查找操作分析
LinkedList和ArrayList的查找操作略有不同:LinkedList需在鏈表中定位元素,而ArrayList則能直接訪問數組中的元素。
五、刪除操作分析
刪除操作中,LinkedList的效率較高,因為它僅需調整前後指針,而無需移動大量數據。
六、結論
在不同操作場景下,選擇合適的數據結構至關重要。通常情況下,
讀取操作推薦使用ArrayList,插入操作推薦使用LinkedList,單線程環境下可選擇Vector,而Stack適用於遵循FILO原則的場景。