java单链表节点翻转_Java数据结构01-链表基础(讲解+代码+面试题)
文章結(jié)構(gòu)
鏈表
鏈表包含單鏈表,雙向鏈表,循環(huán)鏈表等等。相對(duì)于線性表,添加,刪除操作非常方便,因?yàn)椴挥靡苿?dòng)大量的節(jié)點(diǎn),只需要修改對(duì)應(yīng)的前后節(jié)點(diǎn)指針即可。下面用一個(gè)具體實(shí)例來說明下這種結(jié)構(gòu)。現(xiàn)在有一需求,是將具有不同編號(hào),姓名,昵稱的人添加到系統(tǒng)中。首先需要?jiǎng)?chuàng)建節(jié)點(diǎn),既然是鏈表,節(jié)點(diǎn)除了基本信息也要加入下一節(jié)點(diǎn)指針,方便計(jì)算機(jī)在內(nèi)存中查找。
單向鏈表是通過指針構(gòu)建的列表,基本結(jié)構(gòu)就是頭節(jié)點(diǎn)+下一節(jié)點(diǎn)地址指針--->節(jié)點(diǎn)+下一節(jié)點(diǎn)地址指針--->尾節(jié)點(diǎn)。
單鏈表的基本代碼實(shí)現(xiàn)
在這里強(qiáng)推一波韓順平的Java數(shù)據(jù)結(jié)構(gòu)網(wǎng)課,講的由淺入深,筆記詳細(xì)。當(dāng)然自己看視頻之后自己再寫才是正道。
https://www.bilibili.com/video/av54029771?from=search&seid=15096936792873170656?www.bilibili.comclass HeroNode{public int no; //編號(hào)public String name; //姓名public String nickname;//昵稱public HeroNode next; //下一節(jié)點(diǎn)指針//構(gòu)造器public HeroNode(int no, String name, String nickname) {this.no = no;this.name = name;this.nickname = nickname; }@Overridepublic String toString() {return "HeroNode [no = " + no + ", name " + name + ", nickname = " + nickname;}}下一步是創(chuàng)建鏈表類,包括一些基本操作方法
class SingleLinkedList{//初始化頭節(jié)點(diǎn),頭節(jié)點(diǎn)不動(dòng)private HeroNode head = new HeroNode(0, "", "");//返回頭節(jié)點(diǎn),方便后續(xù)操作public HeroNode getHead() {return head;}//添加節(jié)點(diǎn)內(nèi)到單向鏈表//思路,當(dāng)不考慮編號(hào)順序,找到當(dāng)前鏈表的最后節(jié)點(diǎn),將最后節(jié)點(diǎn)的next指向新節(jié)點(diǎn)public void add(HeroNode heroNode) {HeroNode temp = head;//遍歷鏈表,找到最后while(true) {if(temp.next == null) {break;}//如果沒有找到,將temp后移temp = temp.next;}temp.next = heroNode;}//按照順序添加public void addByOrder(HeroNode heroNode) {//頭節(jié)點(diǎn)不能動(dòng),通過輔助指針//單鏈表,因此temp在添加位置的前一個(gè)結(jié)點(diǎn)HeroNode temp = head;boolean flag = false; //編號(hào)是否存在while(true) {if(temp.next == null) {//鏈表最后break;}if(temp.next.no > heroNode.no) {//位置找到break;}else if(temp.next.no == heroNode.no){//編號(hào)存在flag = true; }temp = temp.next;}if(flag) {System.out.printf("編號(hào)%d存在", heroNode.no);}else {heroNode.next = temp.next;temp.next = heroNode;}}//更新鏈表,在找到序號(hào)的情況下進(jìn)行更新public void update(HeroNode newHeroNode) {//根據(jù)no修改if(head.next == null) {System.out.println("鏈表為空");return;}HeroNode temp = head.next;boolean flag = false;while(true) {if(temp == null) {break;}if(temp.no == newHeroNode.no) {flag = true;break;}temp = temp.next;}if(flag) {temp.name = newHeroNode.name;temp.nickname = newHeroNode.nickname;}else {System.out.printf("沒找編號(hào)%d的值", newHeroNode.no);}}//刪除節(jié)點(diǎn)//head不動(dòng),找到被刪除節(jié)點(diǎn)的前一個(gè)public void del(int no) {HeroNode temp = head;boolean flag = false;while(true) {if(temp.next == null) {break;}if (temp.next.no == no) {flag = true;break;}temp = temp.next;}if(flag) {temp.next = temp.next.next;}else {System.out.printf("要?jiǎng)h除的節(jié)點(diǎn)%d不存在", no);}} }這里說下頭節(jié)點(diǎn)存在的意義:
1.防止單鏈表是空的而設(shè)的,否則空鏈表頭指針就會(huì)指向null.
2.方便插入表頭或者刪除第一個(gè)結(jié)點(diǎn)
劍指offer涉及到的鏈表題目
第一題:從尾到頭打印鏈表
思路:遞歸,深入到最底層取出節(jié)點(diǎn).val值后一層一層回退
import java.util.ArrayList; public class Solution {ArrayList<Integer> list = new ArrayList<Integer>();public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {if(listNode != null){this.printListFromTailToHead(listNode.next);list.add(listNode.val);}return list;} }第二題:輸入一個(gè)鏈表,輸出該鏈表中倒數(shù)第k個(gè)結(jié)點(diǎn)。
思路1 傳統(tǒng)法得到鏈表長度L,再從頭遍歷到L-k個(gè)
思路2 快慢指針,慢指針距離快指針始終k,當(dāng)快指針到最后的null時(shí)候,輸出慢指針
代碼是思路2
public class Solution {public ListNode FindKthToTail(ListNode head,int k) {//快慢指針ListNode fast = head;ListNode slow = head;for(int i = 0; i < k; i++){if(fast == null){return null;} fast = fast.next;}while(fast != null){fast = fast.next;slow = slow.next;}return slow;} }第三題:輸入一個(gè)鏈表,反轉(zhuǎn)鏈表后,輸出新鏈表的表頭。
思路:本能反應(yīng)是遍歷到最后,倒數(shù)第二,第三以此類推,但是這樣每次都遍歷一遍鏈表花銷太大。最清真的思路是采用頭插法,先建立一個(gè)新的頭節(jié)點(diǎn),依次將鏈表中的節(jié)點(diǎn)插入到新頭節(jié)點(diǎn)后邊的第一個(gè)位置,以此類推。這里需要注意的是為了防止斷鏈,要建立額外指針來儲(chǔ)存當(dāng)前插入點(diǎn)current在原鏈表的下一個(gè)節(jié)點(diǎn)。
題外話:韓老師的視頻里面頭節(jié)點(diǎn)是沒有數(shù)據(jù)的,這個(gè)題目Head是有數(shù)據(jù)的,害得我提交很多次都不合格。下面這個(gè)是head無數(shù)據(jù)版本
public class Solution {public ListNode ReverseList(ListNode head) {if(head.next == null || head.next.next == null) {return head;}//輔助指針,遍歷原來的鏈表ListNode cur = head.next.next;ListNode next = null; //指向cur的下一個(gè)節(jié)點(diǎn) 防止斷鏈ListNode reverseHead = null;while( cur != null) {next = cur.next;//暫時(shí)保存后面有用cur.next = reverseHead.next;//cur的下一個(gè)節(jié)點(diǎn)指向新鏈表的最前端reverseHead.next = cur;//cur連接到新的鏈表最頂端cur = next;}return reverseHead;} }下面這個(gè)是head有數(shù)據(jù)版本
public class Solution {public ListNode ReverseList(ListNode head) {if(head==null)return null;ListNode pre = null;ListNode next = null;while(head!=null){next = head.next;head.next = pre;pre = head;head = next;}return pre;} }第四題:合并兩個(gè)有序鏈表
/* public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;} }*/ public class Solution {public ListNode Merge(ListNode list1, ListNode list2) {if (list1 == null) {return list2;}if (list2 == null) {return list1;}ListNode temp = null;ListNode mergeHead = null;while (list1 != null && list2 != null) {if (list1.val < list2.val) {if (mergeHead == null) {mergeHead = list1;temp = list1;} else {temp.next = list1;temp = temp.next;}list1 = list1.next;} else {if (mergeHead == null) {mergeHead = list2;temp = list2;} else {temp.next = list2;temp = temp.next;}list2 = list2.next;}}if (list1 == null) {temp.next = list2;} else {temp.next = list1;}return mergeHead;} }總結(jié)
以上是生活随笔為你收集整理的java单链表节点翻转_Java数据结构01-链表基础(讲解+代码+面试题)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html 进入效果,用css3实现简单的
- 下一篇: java支持多线程吗_Java多线程之一