前言
數據結構是計算機存儲、組織數據的方式。如果不會數據結構,那麼就不可能寫出好的代碼,因此。數據結構是我們學習編程不可或缺的一部分!鏈表是數據結構中的一種,但是鏈表又分爲單向鏈表,雙向鏈表,循環鏈表,本篇文章主要是聊聊鏈表中的單向鏈表。
單向鏈表(single-linked list)概述
一個單鏈表的節點(Node)分爲兩部分,第一個部分(data)保存或者顯示關於節點的信息,另一個部分儲存下一個節點的地址,最後一個節點的儲存地址部分指向空值。
單向表只可向一個方向便利,一般查找一個節點的時候需要從第一個節點開始每次訪問下一個節點,一直訪問到需要的位置。而插入一個節點,對於單向鏈表,我們只提供在鏈表頭插入,只需要將當前的節點設置爲頭節點,next指向源頭節點即可。刪除一個節點,我們將該節點的上一個的next指向下一個節點
算法分析:
鏈表中元素的增加(需要按照編號的順序添加):
- 首先找到新添加的節點的位置, 是通過輔助變量(指針), 通過遍歷來搞定
- (新的節點)heroNode.next = temp.next
- 將temp.next = heroNode.next(新的節點)
鏈表中元素的刪除(需要按照編號進行刪除):
- 我們先找到需要刪除的這個節點的前一個節點 temp
- temp.next.no = herNode.next(temp.next.next)
- 被刪除的節點,將不會有其它引用指向,會被垃圾回收機制回收
鏈表中元素的修改(需要按照編號進行刪除):
1、按照no找到要修改的編號
2、temp.name=newHeroNode.name;
3、temp.nickName=newHeroNode.nickName;注意事項:
在創建、修改、刪除中所創建的輔助變量temp都是必須的,因爲head的值是不能變化的,一旦head發生變化,整個鏈表就會報錯。
代碼實現:
public class SingleLinkedListDemo {
public static void main(String[] args) {
HeroNode hero1=new HeroNode(1, "宋江", "及時雨");
HeroNode hero2=new HeroNode(2, "盧俊義", "玉麒麟");
HeroNode hero3=new HeroNode(3, "吳用", "智多星");
HeroNode hero4=new HeroNode(4, "林沖", "豹子頭");
SingleLinkedList singleLinkedList = new SingleLinkedList();
//singleLinkedList.add(hero1);
//singleLinkedList.add(hero2);
//singleLinkedList.add(hero3);
//singleLinkedList.add(hero4);
singleLinkedList.addByOrder(hero1);
singleLinkedList.addByOrder(hero4);
singleLinkedList.addByOrder(hero2);
singleLinkedList.addByOrder(hero3);
singleLinkedList.addByOrder(hero3);
System.out.println("修改前:");
singleLinkedList.list();
HeroNode newHeroNode =new HeroNode(2, "小盧", "小麒麟");
singleLinkedList.update(newHeroNode);
System.out.println("修改後:");
singleLinkedList.list();
singleLinkedList.delete(hero3);
System.out.println("刪除後:");
singleLinkedList.list();
}
}
class SingleLinkedList{
//先初始化一個頭結點,頭結點不要動,不存放具體數據
private HeroNode head = new HeroNode(0, "", "");
public void add(HeroNode heroNode) {
HeroNode temp = head;//定義一個輔助變量來存放head,因爲head是不可變的
//遍歷鏈表,找到最後
while(true) {
if(temp.next==null) {
break;//找到鏈表的最後一個之後。break
}
//如果沒有找到,就將temp後移,當退除循環時,temp指向鏈表的最後
temp = temp.next;
}
//temp指向新的節點
temp.next = heroNode;
}
public void addByOrder(HeroNode heroNode) {
HeroNode temp = head;
//因爲時單鏈表,因此我們要找的temp是位於插入節點前一個位置的否則插入不了
boolean flag = false;//flag標誌添加的編號是否存在,默認爲false
while(true) {
if(temp.next==null)//temp已經再鏈表的最後,break
break;
if(temp.next.no>heroNode.no)//與添加位置的後一位no進行比較,位置已找到
break;
else if(temp.next.no==heroNode.no){//說明希望添加的heroNode的編號已經存在
flag = true;
break;
}
temp = temp.next;
}
if(flag == true) {
System.out.printf("準備插入的這個英雄的編號%d已經存在,不能加入",heroNode.no);
System.out.println();
}
else {
//插入到鏈表中
heroNode.next=temp.next;
temp.next=heroNode;
}
}
//修改節點的信息,no不能更改
public void update(HeroNode newHeroNode) {
if(head.next==null) {
System.out.println("LinkedList爲空");
return;
}
HeroNode temp = head;
boolean flag = false;
while(true) {
if(temp.next==null)//已經遍歷完鏈表
break;
if(temp.no==newHeroNode.no)
{
flag = true;
break;
}
temp = temp.next;
}
if(flag == true) {
temp.name=newHeroNode.name;
temp.nickName=newHeroNode.nickName;
}
else {
System.out.printf("沒有找到編號等於%d的節點",newHeroNode.no);
}
}
public void delete(HeroNode heroNode) {
if(head.next==null) {
System.out.println("該鏈表爲空,無法刪除");
return;
}
HeroNode temp = head;
boolean flag = false;
while(true) {
if(temp.next==null)
break;
if(temp.next.no==heroNode.no) {
flag = true;
break;
}
temp = temp.next;
}
if(flag == true) {
temp.next=heroNode.next;
}
else {
System.out.printf("要刪除的no爲%d的節點不存在",heroNode.no);
}
}
//顯示鏈表(遍歷)
public void list() {
//先判斷鏈表是否爲空
if(head.next==null) {
return;
}
//因爲頭節點不能動,因此需要一個輔助變量
HeroNode temp = head.next;
while(true) {
if(temp==null) {
break;
}
System.out.println(temp.toString());
temp = temp.next;//後移
}
}
}
//定義一個HeroNode,每個HeroNode代表一個結點
class HeroNode {
public int no;
public String name;
public String nickName;
public HeroNode next;//指向下一個結點
public HeroNode(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "HeroNode [no=" + no + ", name=" + name + ", nickName=" + nickName + "]";
}
}