生活中的鏈表
鏈表其實是一個一環扣一環的東西,最簡單明瞭的就是我們的鏈子了,它就是一個一環扣一環的東西
鏈表介紹
- 鏈表在內存中的圖解可以用下圖來表示
- 鏈表是以節點的方式存儲,是一個鏈式存儲。
- 每個節點都有一個data域,和一個next域。
- 鏈表的內存空間可能是不連續的。
- 鏈表有帶頭節點和不帶頭節點兩種,具體使用哪一種視情況而定。
單鏈表的代碼書寫
單鏈表的數據模型
單鏈表書寫
這裏我們使用一個學生作爲節點類,來完成對鏈表的增加節點,刪除節點,修改節點,遍歷整個鏈表並打印輸出。
public class Student {
private String name;
private int no;
private Student next;
public Student() {
}
public Student(String name,int no) {
this.name = name;
this.no = no;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName() {
this.name = name;
}
public Student getNext() {
return next;
}
public Student setNext() {
this.next = next;
}
}
/**
* 這是一個帶頭節點的鏈表模擬
*/
public class LinkListDemo {
public Student head = new Student(); // 設置頭節點,沒有實際數據存放
/**
* 將數據按照no順序添加到鏈表中
* 實現思路:如果head的next域爲空則直接插入到next域中
* 如果head節點的next域不爲空,則遍歷該節點,當節點的next域no大於要插入的
* 節點no,則將其插入在當前節點的next域
* 如果沒有符合條件的,則插入在該鏈表的最後
* @param stu 學生節點
* @return 添加成功返回true, 失敗返回false
*/
public boolean addLink(Student stu) {
if (head.getNext() == null) {
head.setNext(stu);
} else {
Student temp = head;
boolean flag= true;
while (true) {
if (temp.getNext() == null) {
break;
}else if (temp.getNext().getNo() == stu.getNo()) {
flag == false;
break;
} else if (temp.getNext().getNo() > stu.getNo()) {
break;
}
temp = temp.getNext();
}
if (flag) {
stu.setNext(temp.getNext());
tem.setNext(stu);
} else {
System.out.print("該no已經在這個鏈表中存在了");
}
return flag;
}
}
/**
* 刪除鏈表中的節點
* 實現思路:如果head的next域爲空,則直接返回false
* 如果head域不爲空,則遍歷該鏈表,找到則將該節點刪除,否則返回false
* @param stu 需要刪除的節點
* @return 刪除成功返回true ,失敗false
*/
public boolean delLink(Student stu) {
boolean flag = false;
if (head.getNext() == null) {
System.out.print("鏈表爲空!!找不到元素");
return flag;
}
Student temp = head;
while (true) {
if (temp.getNext() == null) {
break;
} else if (temp.getNext().getNo == stu.getNo()) {
flag = true;
break;
}
temp = temp.getNext();
}
if (flag) {
temp.setNext(temp.getNext().getNext());
}
return flag;
}
/**
* 修改鏈表中的節點
* 實現思路:如果head的next域爲空,則直接返回false
* 如果head域不爲空,則遍歷該鏈表,找到則將該節點修改,否則返回false
* @param stu 需要刪除的節點
* @return 刪除成功返回true ,失敗false
*/
public boolean upLink(Student stu) {
boolean flag = false;
if (head.getNext() == null) {
System.out.print("鏈表爲空!!找不到元素");
return flag;
}
Student temp = head;
while (true) {
if (temp.getNext() == null) {
break;
} else if (temp.getNo == stu.getNo()) {
flag = true;
break;
}
temp = temp.getNext();
}
if (flag) {
tem.setNo(stu.getNo());
tem.setName(stu.getName());
}
return flag;
}
}
面試題分享
- 計算單鏈表中有效元素個數
/**
* 實現思路:
* 遍歷鏈表,計算其有效元素個數
* @param node需要計算的鏈表
* @return 計算得到的鏈表有效元素個數
*/
public static int getLength(Student head) {
if (null == head.getNext()) {
return 0;
}
Student temp = head.getNext();
int count = 0;
while (null != temp.getNext()) {
temp = temp.getNext();
count++;
}
return count;
}
- 查找單鏈表中倒數第K個節點
/**
* 實現思路:
* 1. 計算鏈表中有效元素個數length
* 2. 通過length - index 就是我們正方向數的下標位置
* 3. 遍歷鏈表,找到指定下標的位置
* @param head 鏈表的頭節點
* @param lastIndex需要查找的下標位置
* @return 找到則返回student對象,沒有找到返回null
*/
public static Student findLastIndexNode(Student head, int lastIndex) {
if (head.getNext() == null) {
throw new NullPointsException();
}
int size = getLength(head);
int index = size - lastIndex;
Student temp = head.getNext();
int count = 0;
while (count < index) {
temp = temp.getNext();
count++;
}
}
- 單鏈表的反轉
/**
* 實現思路:
* 1. 新創建一個臨時鏈表的頭節點
* 2. 遍歷需要反轉的鏈表
* 3. 將取下的節點插在臨時鏈表頭的next節點上
* 4. 將臨時節點頭的next拼接在head頭節點next上
* 5. 完成鏈表反轉
* @param head 需要反轉的鏈表
*/
public static void reverseList(Student head) {
if (null == head.getNext()) {
throw new RuntimeException("鏈表爲空!!!");
}
// 創建一個新的鏈表
Student tempHead = new Student();
Student temp = head.getNext();
// 記錄下當前節點的下一個節點
Student next = null;
while (temp != null) {
next = temp.getNext();
temp.setNext(tempHead.getNext());
tempHead.setNext(temp);
temp = next;
}
head.setNext(tempHead.getNext());
}