java链表实现_链表的原理及java实现
一:單向鏈表基本介紹
鏈表是一種數(shù)據(jù)結(jié)構(gòu),和數(shù)組同級(jí)。比如,Java中我們使用的ArrayList,其實(shí)現(xiàn)原理是數(shù)組。而LinkedList的實(shí)現(xiàn)原理就是鏈表了。鏈表在進(jìn)行循環(huán)遍歷時(shí)效率不高,但是插入和刪除時(shí)優(yōu)勢(shì)明顯。下面對(duì)單向鏈表做一個(gè)介紹。
單向鏈表是一種線性表,實(shí)際上是由節(jié)點(diǎn)(Node)組成的,一個(gè)鏈表?yè)碛胁欢〝?shù)量的節(jié)點(diǎn)。其數(shù)據(jù)在內(nèi)存中存儲(chǔ)是不連續(xù)的,它存儲(chǔ)的數(shù)據(jù)分散在內(nèi)存中,每個(gè)結(jié)點(diǎn)只能也只有它能知道下一個(gè)結(jié)點(diǎn)的存儲(chǔ)位置。由N各節(jié)點(diǎn)(Node)組成單向鏈表,每一個(gè)Node記錄本Node的數(shù)據(jù)及下一個(gè)Node。向外暴露的只有一個(gè)頭節(jié)點(diǎn)(Head),我們對(duì)鏈表的所有操作,都是直接或者間接地通過(guò)其頭節(jié)點(diǎn)來(lái)進(jìn)行的。
?
上圖中最左邊的節(jié)點(diǎn)即為頭結(jié)點(diǎn)(Head),但是添加節(jié)點(diǎn)的順序是從右向左的,添加的新節(jié)點(diǎn)會(huì)被作為新節(jié)點(diǎn)。最先添加的節(jié)點(diǎn)對(duì)下一節(jié)點(diǎn)的引用可以為空。引用是引用下一個(gè)節(jié)點(diǎn)而非下一個(gè)節(jié)點(diǎn)的對(duì)象。因?yàn)橛兄粩嗟囊?#xff0c;所以頭節(jié)點(diǎn)就可以操作所有節(jié)點(diǎn)了。
下圖描述了單向鏈表存儲(chǔ)情況。存儲(chǔ)是分散的,每一個(gè)節(jié)點(diǎn)只要記錄下一節(jié)點(diǎn),就把所有數(shù)據(jù)串了起來(lái),形成了一個(gè)單向鏈表。
?
節(jié)點(diǎn)(Node)是由一個(gè)需要儲(chǔ)存的對(duì)象及對(duì)下一個(gè)節(jié)點(diǎn)的引用組成的。也就是說(shuō),節(jié)點(diǎn)擁有兩個(gè)成員:儲(chǔ)存的對(duì)象、對(duì)下一個(gè)節(jié)點(diǎn)的引用。下面圖是具體的說(shuō)明:
二、單項(xiàng)鏈表的實(shí)現(xiàn)
/***@authorAdministrator*/
public classMyLink {
Node head= null; //頭節(jié)點(diǎn)
/*** 鏈表中的節(jié)點(diǎn),data代表節(jié)點(diǎn)的值,next是指向下一個(gè)節(jié)點(diǎn)的引用
*
*@authorzjn
**/
classNode {
Node next= null;//節(jié)點(diǎn)的引用,指向下一個(gè)節(jié)點(diǎn)
int data;//節(jié)點(diǎn)的對(duì)象,即內(nèi)容
public Node(intdata) {this.data =data;
}
}/*** 向鏈表中插入數(shù)據(jù)
*
*@paramd*/
public void addNode(intd) {
Node newNode= new Node(d);//實(shí)例化一個(gè)節(jié)點(diǎn)
if (head == null) {
head=newNode;return;
}
Node tmp=head;while (tmp.next != null) {
tmp=tmp.next;
}
tmp.next=newNode;
}/***
*@paramindex:刪除第index個(gè)節(jié)點(diǎn)
*@return
*/
public boolean deleteNode(intindex) {if (index < 1 || index >length()) {return false;
}if (index == 1) {
head=head.next;return true;
}int i = 1;
Node preNode=head;
Node curNode=preNode.next;while (curNode != null) {if (i ==index) {
preNode.next=curNode.next;return true;
}
preNode=curNode;
curNode=curNode.next;
i++;
}return false;
}/***
*@return返回節(jié)點(diǎn)長(zhǎng)度*/
public intlength() {int length = 0;
Node tmp=head;while (tmp != null) {
length++;
tmp=tmp.next;
}returnlength;
}/*** 在不知道頭指針的情況下刪除指定節(jié)點(diǎn)
*
*@paramn
*@return
*/
public booleandeleteNode11(Node n) {if (n == null || n.next == null) {return false;
}int tmp =n.data;
n.data=n.next.data;
n.next.data=tmp;
n.next=n.next.next;
System.out.println("刪除成功!");return true;
}public voidprintList() {
Node tmp=head;while (tmp != null) {
System.out.println(tmp.data);
tmp=tmp.next;
}
}public static voidmain(String[] args) {
MyLink list= newMyLink();
list.addNode(5);
list.addNode(3);
list.addNode(1);
list.addNode(2);
list.addNode(55);
list.addNode(36);
System.out.println("linkLength:" +list.length());
System.out.println("head.data:" +list.head.data);
list.printList();
list.deleteNode(4);
System.out.println("After deleteNode(4):");
list.printList();
}
}
三、鏈表相關(guān)的常用操作實(shí)現(xiàn)方法
1. 鏈表反轉(zhuǎn)
/*** 鏈表反轉(zhuǎn)
*
*@paramhead
*@return
*/
publicNode ReverseIteratively(Node head) {
Node pReversedHead=head;
Node pNode=head;
Node pPrev= null;while (pNode != null) {
Node pNext=pNode.next;if (pNext == null) {
pReversedHead=pNode;
}
pNode.next=pPrev;
pPrev=pNode;
pNode=pNext;
}this.head =pReversedHead;return this.head;
}
2. 查找單鏈表的中間節(jié)點(diǎn)
采用快慢指針的方式查找單鏈表的中間節(jié)點(diǎn),快指針一次走兩步,慢指針一次走一步,當(dāng)快指針走完時(shí),慢指針剛好到達(dá)中間節(jié)點(diǎn)。
/*** 查找單鏈表的中間節(jié)點(diǎn)
*
*@paramhead
*@return
*/
publicNode SearchMid(Node head) {
Node p= this.head, q = this.head;while (p != null && p.next != null && p.next.next != null) {
p=p.next.next;
q=q.next;
}
System.out.println("Mid:" +q.data);returnq;
}
3. 查找倒數(shù)第k個(gè)元素
采用兩個(gè)指針P1,P2,P1先前移K步,然后P1、P2同時(shí)移動(dòng),當(dāng)p1移動(dòng)到尾部時(shí),P2所指位置的元素即倒數(shù)第k個(gè)元素 。
/*** 查找倒數(shù) 第k個(gè)元素
*
*@paramhead
*@paramk
*@return
*/
public Node findElem(Node head, intk) {if (k < 1 || k > this.length()) {return null;
}
Node p1=head;
Node p2=head;for (int i = 0; i < k; i++)//前移k步
p1 =p1.next;while (p1 != null) {
p1=p1.next;
p2=p2.next;
}returnp2;
}
4. 對(duì)鏈表進(jìn)行排序
/*** 排序
*
*@return
*/
publicNode orderList() {
Node nextNode= null;int tmp = 0;
Node curNode=head;while (curNode.next != null) {
nextNode=curNode.next;while (nextNode != null) {if (curNode.data >nextNode.data) {
tmp=curNode.data;
curNode.data=nextNode.data;
nextNode.data=tmp;
}
nextNode=nextNode.next;
}
curNode=curNode.next;
}returnhead;
}
5. 刪除鏈表中的重復(fù)節(jié)點(diǎn)
/*** 刪除重復(fù)節(jié)點(diǎn)*/
public voiddeleteDuplecate(Node head) {
Node p=head;while (p != null) {
Node q=p;while (q.next != null) {if (p.data ==q.next.data) {
q.next=q.next.next;
}elseq=q.next;
}
p=p.next;
}
}
6. 從尾到頭輸出單鏈表,采用遞歸方式實(shí)現(xiàn)
/*** 從尾到頭輸出單鏈表,采用遞歸方式實(shí)現(xiàn)
*
*@parampListHead*/
public voidprintListReversely(Node pListHead) {if (pListHead != null) {
printListReversely(pListHead.next);
System.out.println("printListReversely:" +pListHead.data);
}
}
7. 判斷鏈表是否有環(huán),有環(huán)情況下找出環(huán)的入口節(jié)點(diǎn)
/*** 判斷鏈表是否有環(huán),單向鏈表有環(huán)時(shí),尾節(jié)點(diǎn)相同
*
*@paramhead
*@return
*/
public booleanIsLoop(Node head) {
Node fast= head, slow =head;if (fast == null) {return false;
}while (fast != null && fast.next != null) {
fast=fast.next.next;
slow=slow.next;if (fast ==slow) {
System.out.println("該鏈表有環(huán)");return true;
}
}return !(fast == null || fast.next == null);
}/*** 找出鏈表環(huán)的入口
*
*@paramhead
*@return
*/
publicNode FindLoopPort(Node head) {
Node fast= head, slow =head;while (fast != null && fast.next != null) {
slow=slow.next;
fast=fast.next.next;if (slow ==fast)break;
}if (fast == null || fast.next == null)return null;
slow=head;while (slow !=fast) {
slow=slow.next;
fast=fast.next;
}returnslow;
}
轉(zhuǎn)載自:https://blog.csdn.net/jianyuerensheng/article/details/51200274
總結(jié)
以上是生活随笔為你收集整理的java链表实现_链表的原理及java实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 1011. World Cup Bett
- 下一篇: APQC 7.0.5通用版流程框架