1.2單鏈表的增刪改查(curd)





package com.atguigu.linkedlist;

import java.util.Stack;

public class SingleLinkedListDemo {

public static void main(String[] args) {

//進(jìn)行測(cè)試

//先創(chuàng)建節(jié)點(diǎn)

HeroNode hero1 = new HeroNode(1, "宋江", "及時(shí)雨");

HeroNode hero2 = new HeroNode(2, "盧俊義", "玉麒麟");

HeroNode hero3 = new HeroNode(3, "吳用", "智多星");

HeroNode hero4 = new HeroNode(4, "林沖", "豹子頭");

//創(chuàng)建要給鏈表

SingleLinkedList singleLinkedList = new SingleLinkedList();

//加入

singleLinkedList.add(hero1);

singleLinkedList.add(hero4);

singleLinkedList.add(hero2);

singleLinkedList.add(hero3);

// 測(cè)試一下單鏈表的反轉(zhuǎn)功能

System.out.println("原來鏈表的情況~~");

singleLinkedList.list();

// System.out.println("反轉(zhuǎn)單鏈表~~");

// reversetList(singleLinkedList.getHead());

// singleLinkedList.list();

System.out.println("測(cè)試逆序打印單鏈表, 沒有改變鏈表的結(jié)構(gòu)~~");

reversePrint(singleLinkedList.getHead());

/*

//加入按照編號(hào)的順序

singleLinkedList.addByOrder(hero1);

singleLinkedList.addByOrder(hero4);

singleLinkedList.addByOrder(hero2);

singleLinkedList.addByOrder(hero3);

//顯示一把

singleLinkedList.list();

//測(cè)試修改節(jié)點(diǎn)的代碼

HeroNode newHeroNode = new HeroNode(2, "小盧", "玉麒麟~~");

singleLinkedList.update(newHeroNode);

System.out.println("修改后的鏈表情況~~");

singleLinkedList.list();

//刪除一個(gè)節(jié)點(diǎn)

singleLinkedList.del(1);

singleLinkedList.del(4);

System.out.println("刪除后的鏈表情況~~");

singleLinkedList.list();

//測(cè)試一下 求單鏈表中有效節(jié)點(diǎn)的個(gè)數(shù)

System.out.println("有效的節(jié)點(diǎn)個(gè)數(shù)=" + getLength(singleLinkedList.getHead()));//2

//測(cè)試一下看看是否得到了倒數(shù)第K個(gè)節(jié)點(diǎn)

HeroNode res = findLastIndexNode(singleLinkedList.getHead(), 3);

System.out.println("res=" + res);

*/

}

//方式2:

//可以利用棧這個(gè)數(shù)據(jù)結(jié)構(gòu),將各個(gè)節(jié)點(diǎn)壓入到棧中,然后利用棧的先進(jìn)后出的特點(diǎn),就實(shí)現(xiàn)了逆序打印的效果

public static void reversePrint(HeroNode head) {

if(head.next == null) {

return;//空鏈表,不能打印

}

//創(chuàng)建要給一個(gè)棧,將各個(gè)節(jié)點(diǎn)壓入棧

Stack<HeroNode> stack = new Stack<HeroNode>();

HeroNode cur = head.next;

//將鏈表的所有節(jié)點(diǎn)壓入棧

while(cur != null) {

stack.push(cur);

cur = cur.next; //cur后移,這樣就可以壓入下一個(gè)節(jié)點(diǎn)

}

//將棧中的節(jié)點(diǎn)進(jìn)行打印,pop 出棧

while (stack.size() > 0) {

System.out.println(stack.pop()); //stack的特點(diǎn)是先進(jìn)后出

}

}

//將單鏈表反轉(zhuǎn)

public static void reversetList(HeroNode head) {

//如果當(dāng)前鏈表為空,或者只有一個(gè)節(jié)點(diǎn),無需反轉(zhuǎn),直接返回

if(head.next == null || head.next.next == null) {

return ;

}

//定義一個(gè)輔助的指針(變量),幫助我們遍歷原來的鏈表

HeroNode cur = head.next;

HeroNode next = null;// 指向當(dāng)前節(jié)點(diǎn)[cur]的下一個(gè)節(jié)點(diǎn)

HeroNode reverseHead = new HeroNode(0, "", "");

//遍歷原來的鏈表,每遍歷一個(gè)節(jié)點(diǎn),就將其取出,并放在新的鏈表reverseHead 的最前端

//動(dòng)腦筋

while(cur != null) {

next = cur.next;//先暫時(shí)保存當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn),因?yàn)楹竺嫘枰褂?/p>

cur.next = reverseHead.next;//將cur的下一個(gè)節(jié)點(diǎn)指向新的鏈表的最前端

reverseHead.next = cur; //將cur 連接到新的鏈表上

cur = next;//讓cur后移

}

//將head.next 指向 reverseHead.next , 實(shí)現(xiàn)單鏈表的反轉(zhuǎn)

head.next = reverseHead.next;

}

//查找單鏈表中的倒數(shù)第k個(gè)結(jié)點(diǎn) 【新浪面試題】

//思路

//1. 編寫一個(gè)方法,接收head節(jié)點(diǎn),同時(shí)接收一個(gè)index

//2. index 表示是倒數(shù)第index個(gè)節(jié)點(diǎn)

//3. 先把鏈表從頭到尾遍歷,得到鏈表的總的長度 getLength

//4. 得到size 后,我們從鏈表的第一個(gè)開始遍歷 (size-index)個(gè),就可以得到

//5. 如果找到了,則返回該節(jié)點(diǎn),否則返回nulll

public static HeroNode findLastIndexNode(HeroNode head, int index) {

//判斷如果鏈表為空,返回null

if(head.next == null) {

return null;//沒有找到

}

//第一個(gè)遍歷得到鏈表的長度(節(jié)點(diǎn)個(gè)數(shù))

int size = getLength(head);

//第二次遍歷? size-index 位置,就是我們倒數(shù)的第K個(gè)節(jié)點(diǎn)

//先做一個(gè)index的校驗(yàn)

if(index <=0 || index > size) {

return null;

}

//定義給輔助變量, for 循環(huán)定位到倒數(shù)的index

HeroNode cur = head.next; //3 // 3 - 1 = 2

for(int i =0; i< size - index; i++) {

cur = cur.next;

}

return cur;

}

//方法:獲取到單鏈表的節(jié)點(diǎn)的個(gè)數(shù)(如果是帶頭結(jié)點(diǎn)的鏈表,需求不統(tǒng)計(jì)頭節(jié)點(diǎn))

/**

*

* @param head 鏈表的頭節(jié)點(diǎn)

* @return 返回的就是有效節(jié)點(diǎn)的個(gè)數(shù)

*/

public static int getLength(HeroNode head) {

if(head.next == null) { //空鏈表

return 0;

}

int length = 0;

//定義一個(gè)輔助的變量, 這里我們沒有統(tǒng)計(jì)頭節(jié)點(diǎn)

HeroNode cur = head.next;

while(cur != null) {

length++;

cur = cur.next; //遍歷

}

return length;

}

}

//定義SingleLinkedList 管理我們的英雄

class SingleLinkedList {

//先初始化一個(gè)頭節(jié)點(diǎn), 頭節(jié)點(diǎn)不要?jiǎng)? 不存放具體的數(shù)據(jù)

private HeroNode head = new HeroNode(0, "", "");

//返回頭節(jié)點(diǎn)

public HeroNode getHead() {

return head;

}

//添加節(jié)點(diǎn)到單向鏈表

//思路,當(dāng)不考慮編號(hào)順序時(shí)

//1. 找到當(dāng)前鏈表的最后節(jié)點(diǎn)

//2. 將最后這個(gè)節(jié)點(diǎn)的next 指向 新的節(jié)點(diǎn)

public void add(HeroNode heroNode) {

//因?yàn)閔ead節(jié)點(diǎn)不能動(dòng),因此我們需要一個(gè)輔助遍歷 temp

HeroNode temp = head;

//遍歷鏈表,找到最后

while(true) {

//找到鏈表的最后

if(temp.next == null) {//

break;

}

//如果沒有找到最后, 將將temp后移

temp = temp.next;

}

//當(dāng)退出while循環(huán)時(shí),temp就指向了鏈表的最后

//將最后這個(gè)節(jié)點(diǎn)的next 指向 新的節(jié)點(diǎn)

temp.next = heroNode;

}

//第二種方式在添加英雄時(shí),根據(jù)排名將英雄插入到指定位置

//(如果有這個(gè)排名,則添加失敗,并給出提示)

public void addByOrder(HeroNode heroNode) {

//因?yàn)轭^節(jié)點(diǎn)不能動(dòng),因此我們?nèi)匀煌ㄟ^一個(gè)輔助指針(變量)來幫助找到添加的位置

//因?yàn)閱捂湵?,因?yàn)槲覀冋业膖emp 是位于 添加位置的前一個(gè)節(jié)點(diǎn),否則插入不了

HeroNode temp = head;

boolean flag = false; // flag標(biāo)志添加的編號(hào)是否存在,默認(rèn)為false

while(true) {

if(temp.next == null) {//說明temp已經(jīng)在鏈表的最后

break; //

}

if(temp.next.no > heroNode.no) { //位置找到,就在temp的后面插入

break;

} else if (temp.next.no == heroNode.no) {//說明希望添加的heroNode的編號(hào)已然存在

flag = true; //說明編號(hào)存在

break;

}

temp = temp.next; //后移,遍歷當(dāng)前鏈表

}

//判斷flag 的值

if(flag) { //不能添加,說明編號(hào)存在

System.out.printf("準(zhǔn)備插入的英雄的編號(hào) %d 已經(jīng)存在了, 不能加入\n", heroNode.no);

} else {

//插入到鏈表中, temp的后面

heroNode.next = temp.next;

temp.next = heroNode;

}

}

//修改節(jié)點(diǎn)的信息, 根據(jù)no編號(hào)來修改,即no編號(hào)不能改.

//說明

//1. 根據(jù) newHeroNode 的 no 來修改即可

public void update(HeroNode newHeroNode) {

//判斷是否空

if(head.next == null) {

System.out.println("鏈表為空~");

return;

}

//找到需要修改的節(jié)點(diǎn), 根據(jù)no編號(hào)

//定義一個(gè)輔助變量

HeroNode temp = head.next;

boolean flag = false; //表示是否找到該節(jié)點(diǎn)

while(true) {

if (temp == null) {

break; //已經(jīng)遍歷完鏈表

}

if(temp.no == newHeroNode.no) {

//找到

flag = true;

break;

}

temp = temp.next;

}

//根據(jù)flag 判斷是否找到要修改的節(jié)點(diǎn)

if(flag) {

temp.name = newHeroNode.name;

temp.nickname = newHeroNode.nickname;

} else { //沒有找到

System.out.printf("沒有找到 編號(hào) %d 的節(jié)點(diǎn),不能修改\n", newHeroNode.no);

}

}

//刪除節(jié)點(diǎn)

//思路

//1. head 不能動(dòng),因此我們需要一個(gè)temp輔助節(jié)點(diǎn)找到待刪除節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)

//2. 說明我們?cè)诒容^時(shí),是temp.next.no 和? 需要?jiǎng)h除的節(jié)點(diǎn)的no比較

public void del(int no) {

HeroNode temp = head;

boolean flag = false; // 標(biāo)志是否找到待刪除節(jié)點(diǎn)的

while(true) {

if(temp.next == null) { //已經(jīng)到鏈表的最后

break;

}

if(temp.next.no == no) {

//找到的待刪除節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)temp

flag = true;

break;

}

temp = temp.next; //temp后移,遍歷

}

//判斷flag

if(flag) { //找到

//可以刪除

temp.next = temp.next.next;

}else {

System.out.printf("要?jiǎng)h除的 %d 節(jié)點(diǎn)不存在\n", no);

}

}

//顯示鏈表[遍歷]

public void list() {

//判斷鏈表是否為空

if(head.next == null) {

System.out.println("鏈表為空");

return;

}

//因?yàn)轭^節(jié)點(diǎn),不能動(dòng),因此我們需要一個(gè)輔助變量來遍歷

HeroNode temp = head.next;

while(true) {

//判斷是否到鏈表最后

if(temp == null) {

break;

}

//輸出節(jié)點(diǎn)的信息

System.out.println(temp);

//將temp后移, 一定小心

temp = temp.next;

}

}

}

//定義HeroNode , 每個(gè)HeroNode 對(duì)象就是一個(gè)節(jié)點(diǎn)

class HeroNode {

public int no;

public String name;

public String nickname;

public HeroNode next; //指向下一個(gè)節(jié)點(diǎn)

//構(gòu)造器

public HeroNode(int no, String name, String nickname) {

this.no = no;

this.name = name;

this.nickname = nickname;

}

//為了顯示方法,我們重新toString

@Override

public String toString() {

return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";

}

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容