1. 程式人生 > >資料結構實現 4.2:集合_基於連結串列實現(C++版)

資料結構實現 4.2:集合_基於連結串列實現(C++版)

資料結構實現 4.2:集合_基於連結串列實現(C++版)

1. 概念及基本框架

4.1 中我們通過 二分搜尋樹 實現了集合,這一節我們通過 連結串列 來實現集合。

集合

集合 的基本特性依然要滿足:集合內的元素 不能重複


注:有些集合(多重集合)中元素也可以重複。
4.1 一樣,我們先利用一個由 純虛擬函式 構成的 抽象類 作為一個介面來定義這些操作。具體程式碼如下:

template <class T>
class Set{
public:
	virtual int size() = 0;
	virtual bool isEmpty() = 0;
	//增加操作
	virtual void add(T num) = 0;
	//刪除操作
	virtual void remove(T num) = 0;
	//查詢操作
	virtual bool contains(T num) = 0;
};

下面只需要通過繼承 抽象類

,並且重寫 純虛擬函式 ,就可以完成 集合 的實現。集合類的框架如下:

template <class T>
class LinkedListSet : public Set<T>{
	...
private:
	LinkedList<T> list;
};

同樣,這裡為了避免重複設計就可以相容更多資料型別,引入了 泛型 ,即 模板 的概念。(模板的關鍵字是 classtypename
這裡的 list 表示一個 連結串列 ,同樣,為了保護資料,變數設定為 private
注:這裡沒有顯式的給出建構函式,因為子類中除了連結串列物件之外沒有特別需要初始化的東西。編譯器會預設先呼叫 連結串列

類(即父類)的建構函式,再去呼叫 集合 類(即子類)的建構函式。
實現了前面的程式之後,接下來就是一個集合的增、刪、查以及一些其他基本操作,接下來利用程式碼去實現。

2. 基本操作程式實現

2.1 增加操作

template <class T>
class LinkedListSet : public Set<T>{
public:
	...
	//增加操作
	void add(T num){
		if (!list.contains(num)){
			list.addFirst(num);
		}
	}
	...
};

為了減小時間複雜度,這裡使用針對連結串列第一個元素進行操作,下面的同理。
注:這裡需要進行判斷,因為連結串列中的元素可以重複。

2.2 刪除操作

template <class T>
class LinkedListSet : public Set<T>{
public:
	...
	//刪除操作
	void remove(T num){
		while (list.contains(num)){
			list.removeElement(num);
		}
	}
	...
};

因為我實現的連結串列只能刪除第一個滿足條件元素,為了刪除所有滿足條件元素,需要迴圈判斷。實際實現只需要遍歷一遍連結串列即可完成刪除操作。

2.3 查詢操作

template <class T>
class LinkedListSet : public Set<T>{
public:
	...
	//查詢操作
	bool contains(T num){
		return list.contains(num);
	}
	...
};

2.4 其他操作

集合還有一些其他的操作,包括 集合大小 的查詢等操作。

template <class T>
class LinkedListSet : public Set<T>{
public:
	int size(){
		return list.size();
	}
	bool isEmpty(){
		return list.isEmpty();
	}
	...
};

3. 演算法複雜度分析

3.1 增加操作

函式 最壞複雜度 平均複雜度
add O(n) O(n)

因為需要判斷是否存在該元素,所以需要遍歷一遍整個連結串列。

3.2 刪除操作

函式 最壞複雜度 平均複雜度
remove O(n) = O(n)

3.3 查詢操作

函式 最壞複雜度 平均複雜度
contains O(n) O(n/2) = O(n)

總體情況:

操作 時間複雜度
O(n)
O(n)
O(n)

由於連結串列不具有有序性,所以操作都需要 O(n) 級別的時間複雜度。

4. 完整程式碼

程式完整程式碼(這裡使用了標頭檔案的形式來實現類)如下,本節不再提供 連結串列 類的實現程式碼,如有需要,可參看 2.1
抽象類 介面程式碼:

#ifndef __SET_H__
#define __SET_H__

template <class T>
class Set{
public:
	virtual int size() = 0;
	virtual bool isEmpty() = 0;
	//增加操作
	virtual void add(T num) = 0;
	//刪除操作
	virtual void remove(T num) = 0;
	//查詢操作
	virtual bool contains(T num) = 0;
};

#endif

集合類 程式碼:

#ifndef __LINKEDLISTSET_H__
#define __LINKEDLISTSET_H__

#include "LinkedList.h"
#include "Set.h"

template <class T>
class LinkedListSet : public Set<T>{
public:
	int size(){
		return list.size();
	}
	bool isEmpty(){
		return list.isEmpty();
	}
	//增加操作
	void add(T num){
		if (!list.contains(num)){
			list.addFirst(num);
		}
	}
	//刪除操作
	void remove(T num){
		while (list.contains(num)){
			list.removeElement(num);
		}
	}
	//查詢操作
	bool contains(T num){
		return list.contains(num);
	}
private:
	LinkedList<T> list;
};

#endif