双向循环链表-模板-自定义类型

#include "stdafx.h"
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;

/***     异常类      ***/
class MyException{
private:
	string mesg;
public:
	MyException(const char* str) :mesg(const_cast<char*>(str)){  }
	const string what(){ return mesg; }
};

/*   结点结构体   */
template <class T>
struct DNode{
	T data;
	DNode<T>* prior;
	DNode<T>* next;
	DNode(DNode<T>* ptr = NULL){
		prior = next = ptr;
	}
	DNode(T item, DNode<T>* ptr = NULL){
		prior = next = ptr;
		data = item;
	}
};


/************         双向循环链表类         ************/
// 双向循环链表类
template <typename T>
class DoubleList{
private:
	DNode<T>* head;
public:
	DoubleList();
	DoubleList(T item);
	void AddNodeHead(T item);              // 头插法,插入结点
	void AddNodeTail(T item);              // 尾插法,插入结点
	void ShowAllNodes();                   // 显示所有结点
	void InsertNodestartfromHead(T, int);  // 在指定位置插入结点,从头结点开始
	void InsertNodestartfromTail(T, int);  // 在指定位置插入结点,从尾结点开始
	int GetLength();                       // 获取链表长度
	bool IsEmpty();                        // 判断链表是否为空
	DNode<T>* GetItemByIndex(int);         // 通过下标获取元素的值
	int GetIndexByItem(T);                 // 获取指定元素在链表中的位置
	void ModifyNode(T, int);               // 修改结点
	static T GetInputItem();                      // 获取输入元素
	static int GetInputIndex();                   // 获取输入下标
};

// 获取链表长度
template <typename T>
int DoubleList<T>::GetLength(){
	int n = 0;
	DNode<T>* list = head;
	while (list->next != head){
		list = list->next;
		n++;
	}
	return n;
}

// 构造函数
template <typename T>
DoubleList<T>::DoubleList(){
	head = new DNode<T>;
	head->next = head;
	head->prior = head;
}
// 构造函数,带参数
template <typename T>
DoubleList<T>::DoubleList(T item){
	head = new DNode<T>;
	
	head->next = head;
	head->prior = head;
	head->data = item;
}

// 头插法
template <typename T>
void DoubleList<T>::AddNodeHead(T item){
	DNode<T>* newNode = new DNode<T>;
	newNode->data = item;
	
	newNode->next = head->next;
	newNode->prior = head;
	head->next->prior = newNode;
	head->next = newNode;
}

// 尾插法
template <typename T>
void DoubleList<T>::AddNodeTail(T item){
	DNode<T>* newNode = new DNode<T>;
	newNode->data = item;

	newNode->next = head;
	newNode->prior = head->prior;
	head->prior->next = newNode;
	head->prior = newNode;
}

// 显示所有结点
template <typename T>
void DoubleList<T>::ShowAllNodes(){
	DNode<T>* list = head;
	while (list->next != head){
		list = list->next;
		cout << list->data << endl;
	}
}

// 在指定位置插入结点,从头结点开始
template <typename T>
void DoubleList<T>::InsertNodestartfromHead(T item,int pos){
	if (pos < 0 || pos > GetLength())
		throw MyException("InsertNodestartfromHead, pos out of range");
	int n = 0;
	DNode<T>* list = head;
	while (list->next != head && n < pos){
		list = list->next;
		n++;
	}

	DNode<T>* newNode = new DNode<T>;
	newNode->data = item;

	newNode->next = list->next;
	newNode->prior = list;
	list->next->prior = newNode;
	list->next = newNode;
}
// 在指定位置插入结点,从尾结点开始
template <typename T>
void DoubleList<T>::InsertNodestartfromTail(T item, int pos){
	if (pos < 0 || pos > GetLength())
		throw MyException("InsertNodestartfromHead, pos out of range");
	int n = 0;
	DNode<T>* list = head;
	while (list->prior != head && n < pos){
		list = list->prior;
		n++;
	}

	DNode<T>* newNode = new DNode<T>;
	newNode->data = item;

	newNode->next = list->next;
	newNode->prior = list;
	list->next->prior = newNode;
	list->next = newNode;
}

// 判断链表是否为空
template <typename T>
bool DoubleList<T>::IsEmpty(){
	if (head->next = head) return 1;
	return 0;
}

// 通过下标获取元素的值
template <typename T>
DNode<T>* DoubleList<T>::GetItemByIndex(int index){
	if (index <= 0 || index > GetLength())
		throw MyException("GetItemByIndex, pos out of range");
	int n = 0;
	DNode<T>* list = head;
	while (list->next != head && n < index){
		list = list->next;
		n++;
	}
	return list;
}

// 修改结点
template <typename T>
void DoubleList<T>::ModifyNode(T item, int pos){
	if (pos <= 0 || pos > GetLength())
		throw MyException("ModiyNode, pos out of range.");
	int n = 0;
	DNode<T>* list = head;
	while (list->next != head && n < pos){
		list = list->next;
		n++;
	}
	list->data = item;
}
// 获取指定元素在链表中的位置
template <typename T>
int DoubleList<T>::GetIndexByItem(T item){
	int n = 1;
	DNode<T>* list = head;
	while (list->next != head && n <= GetLength()){
		list = list->next;
		if (list->data == item) 
			return n;
		n++;
	}
	return -1;
}

// 获取输入下标
template <typename T>
int DoubleList<T>::GetInputIndex(){
	cout << "Input index:" << endl;
	int n;
	cin >> n;
	fflush(stdin);
	return n;
}

// 获取输入元素
template <typename T>
T DoubleList<T>::GetInputItem(){
	cout << "Input item:" << endl;
	T data;
	cin >> data;
	fflush(stdin);
	return data;
}

/***************      图书类      ***************/

// 图书类
class Book{
private:
	double price;
	char *bookName;
	int num;
public:
	Book(const char *name="", double price=0.0, int num=0){ 
		bookName = new char[32]{ 0 };
		strcpy(bookName, name);
		this->price = price;
		this->num = num;
	}
	const char* getName(){ return bookName; }
	const int getNum(){ return num; }
	const double getPrice(){ return price; }
	void setName(char *name){ strcpy(this->bookName,name); }
	void setPrice(double price){ this->price = price; }
	void setNum(int num){ this->num = num; }

	friend ostream& operator<<(ostream &out, Book& book);
	friend istream& operator>>(istream &in, Book& book);
	bool operator==(const Book& book);
};

// 输出运算符重载
ostream& operator<<(ostream& out, Book &book){
	out << "《" << setiosflags(ios::right) << book.getName() << "》\t";
	out << book.getPrice() << "$\t" << book.getNum() << endl;
	return out;
}

// 输入运算符重载
istream& operator>>(istream& in, Book &book){
	cout << "book name:";
	in >> book.bookName;
	cout << "book num:";
	in >> book.num;
	cout << "book price:";
	in >> book.price;
	return in;
}

// ==运算符重载
bool Book::operator==(const Book &book){
	if (strcmp(this->bookName, book.bookName) == 0) return 1;
	return 0;
}

/*********         其他函数       **********/

// 菜单
int menu(){
	cout << "\t                       操作选项" << endl;
	cout << "\t1.在开头插入图书信息                 2.在结尾插入图书信息" << endl;
	cout << "\t3.显示所有图书信息                   4.插入图书,从头起始" << endl;
	cout << "\t5.插入图书,从末尾起始                6.获取链表长度" << endl;
	cout << "\t7.通过下标获取结点元素               8.获取图书在链表中的位置" << endl;
	cout << "\t9.修改结点                           0.退出" << endl;
	cout << "SELECT:";
	string sel;
	cin >> sel;
	return atoi(sel.c_str());
}

int main(int argc, char *argv[]){
	DoubleList<Book> books(Book("Index",0,0));
	books.AddNodeHead(Book("C++ Pirmer Plus",78.5,1000));
	books.AddNodeHead(Book("C Pirmer Plus", 65.5, 1001));
	books.AddNodeHead(Book("C# Pirmer Plus", 68.5, 1002));
	books.AddNodeHead(Book("Linux", 78.5, 1003));
	while (true){
		try{
			switch (menu()){
			case 0:
				system("cls");
				cout << "Bey Bey!" << endl;
				return 0;
			case 1:books.AddNodeHead(DoubleList<Book>::GetInputItem()); break;
			case 2:books.AddNodeTail(DoubleList<Book>::GetInputItem()); break;
			case 3:books.ShowAllNodes(); break;
			case 4:books.InsertNodestartfromHead(DoubleList<Book>::GetInputItem(), DoubleList<Book>::GetInputIndex()); break;
			case 5:books.InsertNodestartfromTail(DoubleList<Book>::GetInputItem(), DoubleList<Book>::GetInputIndex()); break;
			case 6:cout << "length = " << books.GetLength() << endl; break;
			case 7:cout << books.GetItemByIndex(DoubleList<Book>::GetInputIndex())->data; break;
			case 8:cout << "index = " << books.GetIndexByItem(DoubleList<Book>::GetInputItem())<< endl; break;
			case 9:books.ModifyNode(DoubleList<Book>::GetInputItem(),DoubleList<Book>::GetInputIndex()); break;
			}
		}
		catch (MyException ex){
			cout << ex.what() << endl;
		}
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值