帶頭結點的單連結串列實現(C++)

東風不破發表於2014-08-13

單連結串列在插入和刪除操作時,有無頭結點的實現是有區別的,總的來說,帶有頭結點的單連結串列實現起來比較方便,而不帶頭結點的單連結串列在鏈首插入和刪除時要特殊處理,以下程式碼是帶有頭結點的單連結串列的實現。

//類定義、模板類的定義

#ifndef IncludeHeadNodeChain_H_H
#define IncludeHeadNodeChain_H_H
#include <iostream>
using std::ostream;
//自定義一個異常類,用於查詢、插入和刪除操作中越界時的異常提示
class OutOfBounds
{
public:
	void msg()
	{std::cout<<"越界"<<std::endl;}
};

template <class T>
class Node
{
private:
	//宣告友元類
	template <class T>
	friend class IncludeHeadNodeChain;
	//定義節點資料
	T data;//資料域
	Node<T> * next;//指標域
};

template <class T>
class IncludeHeadNodeChain
{
private:
	Node<T> * head;
public:
	IncludeHeadNodeChain();
	~IncludeHeadNodeChain();
	bool isEmpty() const;
	bool find_k(int k, T& x) const;//用於發現第k個元素,返回給x
	int search_x(const T& x) const;//用於查詢連結串列中是否有元素x,並返回x的位置
	int length() const {return head->data;}//返回連結串列長度
	IncludeHeadNodeChain<T>& insert(int k, const T& x);
	IncludeHeadNodeChain<T>& del(int k, T& x);
	void output(ostream& os) const;
	//友元類,用於輸出連結串列元素
	template <class T>
	friend ostream& operator<<(ostream& os, const IncludeHeadNodeChain<T>& ihnc);
};

template <class T>
IncludeHeadNodeChain<T>::IncludeHeadNodeChain()
{
	//建立頭結點
	head = new Node<T>;
	head->next = NULL;
	head->data = 0;//本例中頭結點的資料域用於存放連結串列長度
}

template <class T>
IncludeHeadNodeChain<T>::~IncludeHeadNodeChain()
{
	Node<T> * cur = head;
	while (head)
	{
		cur = cur->next;
		delete head;
		head = cur;
	}
}

template <class T>
bool IncludeHeadNodeChain<T>::isEmpty() const
{
	return head->next == NULL;
}

template <class T>
bool IncludeHeadNodeChain<T>::find_k(int k, T& x) const
{
	if (k < 0)
		throw OutOfBounds();
	Node<T> * cur = head;//cur最終指向第k個元素

	for (int i = 0;i < k && cur;i++)
		cur = cur->next;
	if (!cur)
		return false;
	x = cur->data;
	return true;
}

template <class T>
int IncludeHeadNodeChain<T>::search_x(const T& x) const
{
	Node<T> * cur = head->next;
	int index = 1;
	while (cur && cur->data != x)
	{
		cur = cur->next;
		index++;
	}
	if (!cur)
		return -1;//返回-1表示未能找到x
	return index;
}

template <class T>
IncludeHeadNodeChain<T>& IncludeHeadNodeChain<T>::insert(int k, const T& x)
{
	if (k < 0)
		throw OutOfBounds();
	Node<T> * cur = head;
	for (int i = 0;i < k && cur;i++)
		cur = cur->next;
	if (k > 0 && !cur)//若不存在第k個元素
		throw OutOfBounds();
	Node<T> * ins = new Node<T>;//帶插入元素
	ins->data = x;
	//執行插入操作
	ins->next = cur->next;
	cur->next = ins;

	head->data++;//連結串列長度加1
	return *this;
}

template <class T>
IncludeHeadNodeChain<T>& IncludeHeadNodeChain<T>::del(int k, T& x)
{
	if (k < 1) throw OutOfBounds();
	Node<T> * pre = head;//pre最終指向第k個元素的上一個元素
	for (int i = 0;i < k-1 && pre;i++)
		pre = pre->next;
	if (!pre || !pre->next)
		throw OutOfBounds();
	Node<T> * cur = pre->next;//cur指向第k個元素
	//執行刪除操作
	pre->next = cur->next;
	x = cur->data;
	delete cur;

	head->data--;//連結串列長度減1
	return *this;
}

template <class T>
void IncludeHeadNodeChain<T>::output(ostream& os) const
{
	Node<T> * cur = head->next;//cur指向第一個節點
	while (cur)
	{
		std::cout<<cur->data<<" ";
		cur = cur->next;
	}
	std::cout<<std::endl;
}
 
template <class T>
ostream& operator<<(ostream& os, const IncludeHeadNodeChain<T>& ihnc)
{
	ihnc.output(os);
	return os;
}
#endif
使用以下程式碼進行測試:

#include <iostream>
#include "linkedlist.h"

int main()
{
	using std::cout;
	using std::endl;

	IncludeHeadNodeChain<int> chain;
	try
	{
		chain.insert(0,4);
		chain.insert(1,56);
		chain.length();
		//下面程式碼將出現異常
		int x;
		chain.del(3,x);
	}
	catch(OutOfBounds& o)
	{o.msg();}
}


相關文章