一、鏈表的概念
鏈表:採用鏈式存儲結構存儲的線性表,所謂的鏈式是指每個節點保存下一個節點的引用
鏈表的分類:
- 單向、雙向
- 帶頭節點、不帶頭節點
- 循環、非循環
根據以上三種分類,即可組成八種不同類型的鏈表
鏈表的特點:
鏈表結構可以充分利用計算機內存空間,實現靈活的內存動態管理,但是鏈表失去了順序表可以隨機讀取的優點,同時,鏈表增加了節點的指針域,空間開銷比較大。
二、不帶頭單向非循環鏈表
1.結構圖
2. 節點類組成
class Node { //內部節點類
private int data; //節點數據
private Node next; //下一個節點引用
public Node(int data) { //帶參數的構造方法,用於實例化普通節點
this.data = data;
this.next = null;
}
//頭結點
public Node() { //不帶參數的構造方法,用於實例化頭節點
this.data = -1;
this.next = null;
}
}
3. 常用的鏈表操作
1)遍歷鏈表
2)頭插法
3)尾插法
4) 任意位置插入
5) 刪除第一次出現關鍵字爲key的節點
6) 刪除所有關鍵字爲key的節點
7)清空鏈表
4. 接口
public interface ILinked {
//頭插法
void addFirst(int data);
//尾插法
void addLast(int data);
//任意位置插入,第一個數據節點爲0號下標
boolean addIndex(int index,int data);
//查找是否包含關鍵字key是否在單鏈表當中
boolean contains(int key);
//刪除第一次出現關鍵字爲key的節點
int remove(int key);
//刪除所有值爲key的節點
void removeAllKey(int key);
//得到單鏈表的長度
int getLength();
void display();
void clear();
}
5. 實現類
public class MySingleList implements ILinked{
//內部節點類
class Node {
private int data;//存儲該節點中的元素
public Node next;//引用下一個節點
//節點類構造方法
public Node(int data) {
this.data = data;
this.next = null;
}
}
private Node head;//頭節點
//鏈表類構造方法
public MySingleList() {
this.head = null;
}
@Override
//頭插法
public void addFirst(int data) {
Node node = new Node(data);//新建一個插入節點
if(this.head == null) {//頭節點爲空,則插入節點爲頭節點
this.head = node;
}else {//頭節點不爲空
node.next = this.head;
this.head = node;
}
}
@Override
//尾插法
public void addLast(int data) {
Node node = new Node(data);
Node cur = this.head;
//如果是第一次插入
if(cur == null) {
this.head = node;
}else {
//1、找尾巴
while(cur.next != null) {
cur = cur.next;
}
//退出上面的循環,cur所指向的位置就是尾節點
cur.next = node;
}
}
// 返回index位置的節點
private Node searchIndex(int index){
checkIndex(index);
int count=0;
Node cur=this.head;
while(count<index-1){
cur=cur.next;
count++;
}
return cur;
}
//檢驗index位置合法性
private void checkIndex(int index){
if(index<0||index>getLength()){
throw new UnsupportedOperationException("index位置不合法");
}
}
@Override
//任意位置插入
public boolean addIndex(int index, int data) {
if(index==0){
addFirst(data);
return true;
}
Node node =new Node(data);
Node cur=searchIndex(index);
node.next=cur.next;
cur.next=node;
return true;
}
@Override
//查找是否包含關鍵字key是否在單鏈表當中
public boolean contains(int key) {
Node cur=this.head;
while(cur!=null){
if(cur.data==key){
return true;
}
cur = cur.next;
}
return false;
}
private Node searchPrev(int key){
Node cur=this.head;
while(cur.next!=null){
if(cur.next.data==key){
return cur;
}
cur=cur.next;
}
return null;
}
@Override
//刪除第一次出現關鍵字爲key的節點
public int remove(int key) {
if(this.head == null) {
throw new UnsupportedOperationException("單鏈表爲空");
}
int oldData = 0;
//刪除的節點是頭結點
if(this.head.data == key){
oldData = this.head.data;
this.head = this.head.next;
return oldData;
}
Node prev = searchPrev(key);
if(prev == null) {
//return
throw new UnsupportedOperationException("沒有前驅");
}
Node del = prev.next;
oldData = del.data;
prev.next = del.next;
//del = null;
return oldData;
}
//刪除所有關鍵字爲key的節點
public void removeAllKey(int key) {
if(this.head == null) {
return;
}
Node prev = this.head;
Node cur = this.head.next;
while (cur != null) {
if(cur.data == key){
prev.next = cur.next;
cur = prev.next;
}else {
prev = cur;
cur = cur.next;
}
}
if(this.head.data == key){
this.head = this.head.next;
}
}
@Override
public int getLength() {
if(this.head == null) {
return 0;
}
int count = 0;
Node cur = this.head;
while (cur != null){
count++;
cur = cur.next;
}
return count;
}
@Override
public void display() {
Node cur = this.head;
while(cur != null) {
System.out.print(cur.data+" ");
cur = cur.next;
}
System.out.println();
}
@Override
public void clear() {
while (this.head.next != null) {
Node del = this.head.next;
this.head.next = del.next;
}
this.head = null;
}