iT邦幫忙

2023 iThome 鐵人賽

DAY 2
0
自我挑戰組

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

Day02-SLList (sentinel node)

  • 分享至 

  • xImage
  •  

上一章節我們的IntList實作了get和size方法,這邊就來談談add方法。

我們該如何在IntList加元素呢?

IntList L = new IntList(1, null);

// add element to the front [2, 1]
L = new IntList(2, L);

// add element to the last [2, 1, 3]
L.next.next = new IntList(3, null);
...

以上的code就是add最直觀的做法,但會發現這樣真的很難用!該怎麼辦呢?這時候就要發揮Java物件導向的特性,把這些很醜的實作包裝起來,甚至把我們的IntList包裝成另一個類別來重用:

public class SLList{

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

	private IntNode first;
	
	public SLList(){
		first = null;
	}

	public SLList(int num){
		first = new IntNode(num, null);
	}

	public void addFirst(int num){
		first = new IntNode(num, first);
	}

	public void addLast(int num){
		IntNode p = first;
		
		// avoid empty list
		if(p == null){
			p = new IntNode(num, null);
		}

		while(p.next != null){
			p = p.next;
		}
		p.next = new IntNode(num, null);
	}

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

	public int size(){
		return size(first);
  }
	
	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(first, index);
	}
}

不過這樣還不夠好,我們可以發現在addLast(int num)方法中有一個if statement來避免empty list的情況,因為後面會呼叫到p.next,假設我們的first IntNode為null,即假若我們的SLList為空list,就會發生NullPointerException。有沒有什麼辦法讓我們既可以避免掉為了例外而撰寫if statement,又能達到需要的功能呢?

這時老師使用了一個叫sentinel的node:

public class SLList{

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

	private IntNode sentinel;
	
	public SLList(){
		sentinel = new IntNode(69, null);
	}

	public SLList(int num){
		sentinel.next = new IntNode(num, null);
	}

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

	public void addLast(int num){
		IntNode p = sentinel;
		while(p.next != null){
			p = p.next;
		}
		p.next = new IntNode(num, null);
	}

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

	public int size(){
		return size(sentinel.next);
    }
	
	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(sentinel.next, index);
	}
}

我們可以看到,在constructor中我們就會先指派一個IntNode給sentinel,sentinel中的item數值是多少無所謂,因為重要的是連結在它next中的IntNode才會是我們真正的list,所以我們只要把原本code中的first都改為sentinel.next,就搞定了~

如此一來addLast中不但不會遇到空list addList時會拋NullPointerException,判斷p == null的條件也可以去掉!讓code變得更優雅。

license
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License


上一篇
Day01-IntList (LinkedList Intro)
下一篇
Day03-DLList (solve addLast issue)
系列文
資料結構與演算法-CS61B學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言