iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0
自我挑戰組

資料結構與演算法-CS61B學習筆記系列 第 3

Day03-DLList (solve addLast issue)

  • 分享至 

  • xImage
  •  

上一章節我們實作出了一個LinkedList的類別,可以做到基本的操作。不過有一個地方其實有點不太完美,那就是addLast方法的效能不太好,當list的元素很多時,就會跑很久才找到最後一個IntNode,然後assign new IntNode到next變數。

很直覺的想法就是,那我們就多加一個last變數來記錄最後一個node在哪裡囉:

01

而且這個last變數可以在每次執行addLast方法時順便紀錄,貌似一切都很美好~

但其實這樣會有一個問題,那就是當我們要實作remove時,假若我們要remove掉最後一個元素last,我們不能直接把last變數清掉,因為重點在於Linked的前一個關聯要移掉!變成我們還是得從first開始一路找到last的前一個,然後把他的next清掉才是真正的remove。

該怎麼優化呢?那就是在IntNode多加一個prev的屬性!這也是本章節叫做DLList的由來,D代表”doubly” linked list:

02

但這樣實作的話會有個問題,就是當空list時last會指到sentinel node;當list有元素存在時又會指到真正的IntNode:

03

所以這時候就可以現學現賣了,我們的last就一樣使用一個sentinel node:

04

其實上面這個範例在實作上就不會有任何問題了,但是還有一個更精妙的做法,那就是讓sentinel node的prev指向last node!

05

真是優雅。

以下是我實作的扣的:

public class DLListWithLastSentinel {

	private static class IntNode{
		int item;
		IntNode next;
		IntNode prev;
		public IntNode(int i, IntNode n, IntNode p){
			item = i;
			next = n;
			prev = p;
		}
	}	

	private IntNode sentinelFirst;
	private IntNode sentinelLast;
	
	public DLListWithLastSentinel(){
		IntNode first = new IntNode(0, null, null);
		sentinelFirst = first;
		IntNode last = new IntNode(99, null, sentinelFirst);
		sentinelLast = last;
		sentinelFirst.next = sentinelLast;
	}

	public DLListWithLastSentinel(int num){
		IntNode node = new IntNode(num, sentinelLast, sentinelFirst);
		sentinelFirst.next = node;
		sentinelLast.prev = node;
	}

	public void addFirst(int num){
		IntNode oldFirst = sentinelFirst.next;
		sentinelFirst.next = new IntNode(num, oldFirst, sentinelFirst);
		oldFirst.prev = sentinelFirst.next;
	}

	public void addLast(int num){
		IntNode oldLast = sentinelLast.prev;
		sentinelLast.prev = new IntNode(num, sentinelLast, oldLast);
		oldLast.next = sentinelLast.prev;
	}

	private int size(IntNode node){
		if(node.next == null) {
			return 1;
		}
		return 1 + size(node.next);
    }

	public int size(){
		// minus 1 to remove the count of sentinelLast
		return size(sentinelFirst.next) - 1;
    }
	
	private int get(IntNode node, int index) {
		if(index == 0) {
			return node.item;
		}
		return get(node.next, index - 1);
	}
	
	public int get(int index) {
		return get(sentinelFirst.next, index);
	}
}

Slides are from Josh Hug CS61B
license
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License


上一篇
Day02-SLList (sentinel node)
下一篇
Day04-AList (solve ArrayList size issue)
系列文
資料結構與演算法-CS61B學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言