1. 程式人生 > >資料結構學習筆記之列表

資料結構學習筆記之列表

#include <iostream>
using namespace std;
typedef int Rank;
#define Posi(T) ListNode<T>*	//列表節點位置
//節點叫法:頭 首 末 尾
template<typename T>
struct ListNode
{
	T data;	//數值
	Posi(T) pred;	//前驅
	Posi(T) succ;	//後繼
	ListNode() {}	//針對header和trailer的構造
	ListNode(T e, Posi(T) p = NULL, Posi(T) s = NULL) : data(e), pred(p), succ(s) {}//預設構造器
	Posi(T) insertAsPred(T const &e);//前插入
	Posi(T) insertAsSucc(T const &e);//後插入
};

template<typename T>
Posi(T) ListNode<T>::insertAsPred(T const &e)
{
	Posi(T) x = new ListNode(e, pred, this);//新節點的前驅後繼
	pred->succ = x;//舊前去的後繼為新節點
	pred = x;//this的前驅為新節點
	return x;//四個指向完成返回x
}

template<typename T>
Posi(T) ListNode<T>::insertAsSucc(T const &e)
{
	Posi(T) x = new ListNode(e, this, succ);
	succ->pred = x;
	succ = x;
	return x;
}

template<typename T>
class List
{
private:
	int _size; //容量
	Posi(T) header;	//頭節點
	Posi(T) trailer;//尾節點
protected:
	void init();//列表建立時的初始化
	void copyNodes(Posi(T) p, int n);//複製構造
	int clear();//清空列表
public:
	List() { init(); }
	~List();
	void show();
	int deduplicate();//無序唯一化
	int uniquify();//有序唯一化
	T &operator[](Rank r) const;//徇秩訪問,效率低
	T remove(Posi(T) p);//刪除節點
	Posi(T) first() const { return header->succ; }//首節點位置
	Posi(T) last() const { return trailer->pred; }//末節點位置
	//以p為根節點,在他的n個真前驅中找e
	Posi(T) find(T const &e, int n, Posi(T) p) const;
	//p的n個真前驅中,找到不大於e的最後者
	Posi(T) search(T const &e, int n, Posi(T) p) const;
	Posi(T) insertAsFrist(T const &e);//將e作為首節點插入
	Posi(T) insertAsLast(T const &e);//將e作為末節點插入
	Posi(T) insertBefore(Posi(T) p, T const &e);//e作為p的前驅插入
	Posi(T) insertAfter(Posi(T) p, T const &e);//e作為p的後繼插入	
	void selectionSort(Posi(T) p, int n);//p後的n個節點選擇排序
	Posi(T) selectMax(Posi(T) p, int n);//選出最大值
	void insertionSort(Posi(T) p, int n);//p後的n個節點插入排序
};

template<typename T>
void List<T>::init()
{
	header = new ListNode<T>;//建立頭哨兵
	trailer = new ListNode<T>;//建立尾哨兵
	header->succ = trailer;
	header->pred = NULL;
	trailer->pred = header;
	trailer->succ = NULL;
	_size = 0;
}

template<typename T>
void List<T>::copyNodes(Posi(T) p, int n)
{
	init();//建立頭尾
	while(n--)//起自p的n項依次作為末節點插入
	{
		insertAsPred(p->data);
		p = p->succ;
	}
}

template<typename T>
int List<T>::clear()
{
	int oldsize = _size;
	while(0 < _size) remove(header->succ);
	return oldsize;
}

template<typename T>
List<T>::~List()
{
	clear();
	delete header;
	delete trailer;
}

template<typename T>
int List<T>::deduplicate()
{
	if(_size < 2) return 0;
	int oldsize = _size;
	Posi(T) p = first();//從首節點起
	Rank r = 1;
	while(trailer != (p = p->succ))
	{//依次查詢每一個元素是否在前驅中存在
		Posi(T) q = find(p->data, r, p);
		q?remove(q):r++;//存在就刪除
	}
	return oldsize - _size;
}

template<typename T>
int List<T>::uniquify()
{
	if(_size < 2) return 0;
	int oldsize = _size;
	Posi(T) p = first();
	Posi(T) q;
	while(trailer != (q = p->succ))
		if(p->data != q->data)p = q;
		else remove(q);
	return oldsize - _size;
}

template<typename T>
T &List<T>::operator[](Rank r) const //&是後加上去的
{
	Posi(T) p = first(); 	//從首節點出發
	while(0 < r--) p = p->succ; //數出第r個節點
	return p->data;
}

template<typename T>
T List<T>::remove(Posi(T) p)
{
	T e = p->data;
	p->pred->succ = p->succ;
	p->succ->pred = p->pred;
	delete p;
	_size--;
	return e;
}

template<typename T>
Posi(T) List<T>::find(T const &e, int n, Posi(T) p) const
{
	while(0 < n--)
		if(e == (p = p->pred)->data) return p;
	return NULL;
}

template<typename T>
Posi(T) List<T>::search(T const &e, int n, Posi(T) p) const
{
	while(0 <= n--)
		if(((p = p->pred)->data) <= e) break;
	return p;	
}

template<typename T>
Posi(T) List<T>::insertAsFrist(T const &e)
{
	_size++;
	return header->insertAsSucc(e);
}

template<typename T>
Posi(T) List<T>::insertAsLast(T const &e)
{
	_size++;
	return trailer->insertAsPred(e);
}

template<typename T>
Posi(T) List<T>::insertBefore(Posi(T) p, T const &e)
{
	_size++;
	return p->insertAsPred(e);
}

template<typename T>
Posi(T) List<T>::insertAfter(Posi(T) p, T const &e)
{
	_size++;
	return p->insertAsSucc(e);
}

template<typename T>
void List<T>::selectionSort(Posi(T) p, int n)
{
	Posi(T) head = p->pred;
	Posi(T) tail = p;
	for(int i = 0; i < n; i++) tail = tail->succ;
	while(1 < n)
	{
		insertBefore(tail, remove(selectMax(head->succ, n)));
		tail = tail->pred;//每次把最大的放到tail前面,tail前移
		n--;
	}
}

template<typename T>
Posi(T) List<T>::selectMax(Posi(T) p, int n)
{
	Posi(T) max = p;
	for(Posi(T) cur = p; 1 < n; n--)
		if(((cur = cur->succ)->data) >= (max->data))//若cur>=max
			max = cur;
	return max;//返回最大節點位置 
}

template<typename T>
void List<T>::insertionSort(Posi(T) p, int n)
{
	for (int i = 0; i < n; ++i)
	{//假想前面有一個區域i,把p插入到i的合適位置,這樣有序的部分一直增大
		insertAfter(search(p->data, i, p), p->data);
		p = p->succ;
		remove(p->pred);
	}
}//一次插入對應一次銷燬,O(1)輔助空間,原地操

template<typename T>
void List<T>::show()
{
	cout<<_size<<"\t";
	Posi(T) p = first();
	for (int i = 0; i < _size; ++i)
	{
		cout<<p->data<<" ";
		p = p->succ;
	}
	cout<<endl;
}

int main(int argc, char const *argv[])
{
	List<int> a;
	a.insertAsFrist(1);
	a.insertAsLast(9);
	a.insertBefore(a.first(), 0);
	a.insertAfter(a.last(), 19);
	a.insertBefore(a.first(), 9);
	a.insertAfter(a.last(), 1);
	a.deduplicate();
	a.show();
	cout<<a.find(1, 1, a.last())<<endl;
	a.insertBefore(a.first(), 0);
	a.insertAfter(a.last(), 19);
	a.insertBefore(a.first(), 9);
	a.insertAfter(a.last(), 1);
	a.show();	
	a.insertionSort(a.first(), 8);
	a.show();
	return 0;
}