一、連結串列簡介:
連結串列是由記憶體中一系列不相連的結構組成,每一個結構均含有表元素和next指標。優點是插入和刪除比較方便(不需移動其他元素, 只需改變指標),缺點是訪問效率低,儲存空間利用率低。
二、連結串列分類:
單向連結串列
迴圈連結串列
雙向迴圈連結串列
三、以單向連結串列演示連結串列操作
//連結串列操作:插入,刪除,遍歷
class Haha {
public static void main(String[] args){
LinkList theList = new LinkList();
theList.insertFirst(22,2);
theList.insertFirst(33,3);
theList.insertFirst(44,4);
theList.insertFirst(55,5);
theList.insertFirst(66,6);
theList.insertFirst(77,7);
theList.displayList();
while (!theList.isEmpty()){
JieDian aLink = theList.deleteFirst();
System.out.print("Deleted ");
aLink.displayJieDian();
theList.displayList();
System.out.println(" ");
}
theList.displayList();
}
}
class JieDian{
int iData;
double dData;
JieDian next;
JieDian(int id,double dd){
iData = id;
dData = dd;
}
public void displayJieDian(){
System.out.println("{"+iData+","+dData+"}");
}
}
class LinkList{
JieDian first;
LinkList(){
first = null;
}
public boolean isEmpty(){
return (first == null);
}
public void insertFirst(int id,double dd){
JieDian newJieDian = new JieDian(id,dd);
newJieDian.next = first;
first = newJieDian;
}
public JieDian deleteFirst(){
JieDian temp = first;
first = first.next;
return temp;
}
public void displayList(){
System.out.println("List(first -->last):");
JieDian current = first;
while(current != null){
current.displayJieDian();
current = current.next;
}
}
}複製程式碼
結果:
常見問題:
1.判斷一個給定的單連結串列是否有環?
2.環的入口
3.環的長度複製程式碼
第一次相遇時:
slow走的長度S=AB+BC
fast走的長度2S=AB+BC+n*R
AB=n*R-BC
求入口:讓兩個指標同時分別從A、C出發,相遇點就是入口B
求環長:C點相遇之後,指標slow繼續每次走1步,fast每次走2步。在下次相遇的時候fast比slow正好又多走了一圈,也就是多走的距離等於環長。複製程式碼
程式碼:
class Haha {
public static void main(String[] args){
JieDian j1 = new JieDian(11,1);
JieDian j2 = new JieDian(22,2);
JieDian j3 = new JieDian(33,3);
JieDian j4 = new JieDian(44,4);
JieDian j5 = new JieDian(55,5);
JieDian j6 = new JieDian(66,6);
JieDian j7 = new JieDian(77,7);
JieDian j8 = new JieDian(88,8);
JieDian j9 = new JieDian(99,9);
JieDian j10 = new JieDian(110,1);
JieDian j11 = new JieDian(111,1);
j1.next = j2;
j2.next = j3;
j3.next = j4;
j4.next = j5;
j5.next = j6;
j6.next = j7;
j7.next = j8;
j8.next = j9;
j9.next = j10;
j10.next = j11;
j11.next = j5;
//環長
int x = length(hasLoop(j1));
System.out.println(x);
//入口
rukou(j1,hasLoop(j1)).displayJieDian();
}
//入口節點
public static JieDian rukou(JieDian jd1,JieDian jd2){
JieDian a1 = jd1;
JieDian a2 = jd2;
while (true){
a1 = a1.next;
a2 = a2.next;
int d1 = a1.iData;
int d2 = a2.iData;
double t1 = a1.dData;
double t2 = a2.dData;
if(d1 == d2 && t1 == t2){
return a1;
}
}
}
//環長
public static int length(JieDian jd){
JieDian slow = jd;
JieDian fast = jd;
int length = 0;
while(fast != null){
length++;
slow = slow.next;
fast = fast.next.next;
int d1 = slow.iData;
int d2 = fast.iData;
double t1 = slow.dData;
double t2 = fast.dData;
if(d1 == d2 && t1 == t2){
return length;
}
}
return 0;
}
//是否存在環,如果存在,返回相遇的結點
public static JieDian hasLoop(JieDian jd){
JieDian slow = jd;
JieDian fast = jd;
while(fast != null){
slow = slow.next;
fast = fast.next.next;
if(fast == null){
System.out.println("不存在環");
return null;
}
int d1 = slow.iData;
int d2 = fast.iData;
double t1 = slow.dData;
double t2 = fast.dData;
if(d1 == d2 && t1 == t2){
System.out.println("存在環");
return slow;
}
}
return null;
}
}
class JieDian{
int iData;
double dData;
JieDian next;
JieDian(int id,double dd){
iData = id;
dData = dd;
}
public void displayJieDian(){
System.out.println("{"+iData+","+dData+"}");
}
}複製程式碼