数据结构与算法分析-C++描述 第3章 双向链表(通用模板类型/泛型编程)

      写在前面: 使用gcc编译器(其他编译器应该也是)采用“三段式”进行模板类编程时,编译会出现 :error:"collect2: ld returned 1 exit status"

       原因分析:模板不是类和成员函数,模板的具体实现被称为实例化或具体化,除非编译器实现了新的export关键字,否则将模板函数放置在一个独立的文件中将无法运行,因为模板不是函数,它们不能单独编译,模板必须与特定的模板实例化请求一起使用。

        解决办法:1)最简单的办法是所有模板信息放在一个头文件中,并在要使用这些模板的文件中包含该头文件;2)如果编译器实现了新的export关键字,则可以将模板定义放在一个独立的文件中,条件是每个模板声明都必须以export开头,如export template<class dataType> ........。【摘自 《C++ primer 第五版》果然是圣经一样的(好)书 = ~ =】

        方法1方便编译,但单个文件代码量可能很长;方法2可读性更强,但编译可能不太方便,二者各有特色,读者可根据爱好习惯可实际应用,自行选择。

1、list.h 头文件方法声明与实现

//list.h
#ifndef LIST_H_
#define LIST_H_

using std::cout;
using std::endl;
using std::swap;

template<class dataType>
struct Node{
	Node(const dataType d);
	dataType data;
	Node* next;
	Node* prev;
};

template<class dataType>
class List{
private:
	Node<dataType>* head;
	Node<dataType>* tail;
public:
	List();
	List(const List &l);
	List & operator=(List &l);
	~List();
	
	void reverse();
	void print();
	void clear();
	void pushFront(const dataType d);
	void pushBack(const dataType d);
	void popFront();
	void popBack();
	void insert(Node<dataType> *positon, dataType d);
	void erase(Node<dataType> *positon);
	void remove(dataType d);
	Node<dataType>* find(dataType d);
	int count();
};

//Node constructior
template<class dataType>
Node<dataType>::Node(const dataType d):data(d), next(NULL), prev(NULL){}

//List constructior
template<class dataType>
List<dataType>::List():head(NULL), tail(NULL){}

//List copy constructior
template<class dataType>
List<dataType>::List(const List<dataType> &l):head(NULL), tail(NULL){
	if(l.head == NULL){
		return;
	}
	Node<dataType>* temp = l.head;
	while(temp){
		pushBack(temp -> data);
		temp = temp -> next;
	}
}

//List operator=
template<class dataType>
List<dataType>& List<dataType>::operator=(List<dataType> &l){
	if(this != &l){
		std::swap(head, l.head);
		std::swap(tail, l.head);
	}
	return *this;
}

//List destructor
template<class dataType>
List<dataType>::~List(){
	clear();
}

//reverse the List
template<class dataType>
void List<dataType>::reverse(){
	if(head == NULL || head == tail){
		return;
	}
	Node<dataType>* begin = head;
	Node<dataType>* end = tail;
	int num = count();
	while(num){
		if(end -> next == begin){
			break;
		}
		num /= 2;
		std::swap(begin -> data, end -> data);
		begin = begin -> next;
		end = end -> prev;
	}
}

//print the List
template<class dataType>
void List<dataType>::print(){
	if(head == NULL){
		cout << "The List is empty ! " << endl;
	}
	else{
		Node<dataType>* temp = head;
		while(temp){
			cout << temp -> data << " ";
			temp = temp -> next;
		}
		cout << endl;
	}
}

//clear the List
template<class dataType>
void List<dataType>::clear(){
	Node<dataType>* temp = head;
	while(temp -> next != tail){
		head = head -> next;
		delete temp;
		temp = head;
	}
	head = NULL;
	tail = NULL;
}

//push data from the head
template<class dataType>
void List<dataType>::pushFront(const dataType d){
	if(head == NULL){
		pushBack(d);
	}else{
		Node<dataType>* temp = head;
		head = new Node<dataType>(d);
		head -> next = temp;
		temp -> prev = head;
	}
}

//push data from the tail
template<class dataType>
void List<dataType>::pushBack(const dataType data){
	if(head == NULL){
		head = new Node<dataType>(data);
		tail = head;
	}
	else{
		tail -> next = new Node<dataType>(data);
		tail -> next -> prev = tail;
		tail = tail -> next;
	}
}

// pop data from head
template<class dataType>
void List<dataType>::popFront(){
	if(head == NULL){
		cout << "the List is empty ! " << endl;
	}
	else{
		Node<dataType>* temp = head;
		head = head -> next;
		head -> prev = NULL;
		delete temp;
	}
}

//pop data from tail
template<class dataType>
void List<dataType>::popBack(){
	if(head == NULL){
		cout << "the List is empty !" << endl;
	}
	else if(head == tail){
		delete head;
		head = NULL;
		tail = NULL;
	}
	else{
		Node<dataType>* temp = head;
		while(temp -> next != tail){
			temp = temp -> next;
		}
		delete tail;
		tail = temp;
		tail -> prev = temp -> prev;
		tail -> next = NULL;
	}
}

//from Node positon insert Object data
template<class dataType>
void List<dataType>::insert(Node<dataType> *positon, dataType d){
	assert(positon);
	if(positon == tail){
		pushBack(d);
	}
	else{
		Node<dataType>* temp = new Node<dataType>(d);
		temp -> next = positon -> next;
		positon -> next = temp;
		temp -> next -> prev = temp;
		temp -> prev = positon;
	}
}

//erase the data in Node positon
template<class dataType>
void List<dataType>::erase(Node<dataType> *positon){
	assert(positon);
	if(positon == tail){
		popBack();
	}
	else if(positon == head){
		popFront();
	}
	else{
		positon -> prev -> next = positon -> next;
		positon -> next -> prev = positon -> prev;
		delete positon;
	}
}

//remove the data form List
template<class dataType>
void List<dataType>::remove(dataType d){
	if(head == NULL){
		cout << "the List is empty !" << endl;
	}
	else{
		Node<dataType>* temp = find(d);
		if(temp != NULL){
			erase(temp);
		}
	}
}

//find the data in List Node
template<class dataType>
Node<dataType>* List<dataType>::find(dataType d){
	if(head == NULL){
		cout << "the List is empty !" << endl;
		return NULL;
	}
	else{
		Node<dataType>* temp = head;
		while(temp -> next != tail){
			if(temp -> data == d){
				return temp;
			}
			temp = temp -> next;
		}
		return NULL;
	}
}

//count the List elements
template<class dataType>
int List<dataType>::count(){
	if(head == NULL){
		return 0;
	}
	else{
		Node<dataType>* temp = head;
		int num = 0;
		while(temp != tail){
			num++;
			temp = temp -> next;
		}
		return ++num;
	}
}

#endif

2、main.cpp

//main.cpp
#include<iostream>
#include<assert.h>
#include "list.h"

using namespace std;

int main(){
	int array[7] = {3, 4, 2, 6, 5, 1, 7};
	List<int> list;
	for(int i = 0; i < 7; i++){
		list.pushBack(array[i]);
	}
	cout << "The List result : ***************" << endl;
	list.print();
	cout << "The List reverse : **************" << endl;
	list.reverse();
	list.print();
	cout << "the List copy : *****************" << endl;
	List<int> temp = list;
	temp.print();
	cout << "the List popFront : *************" << endl;
	temp.popFront();
	temp.print();
	cout << "the List popBack: ***************" << endl;
	temp.popBack();
	temp.print();
	cout << "the List insert : ***************" << endl;
	list.insert(list.find(2), 4);
	list.print();
	cout << "the List erase : ****************" << endl;
	list.erase(list.find(1));
	list.print();
	cout << "The list remove : ***************" << endl;
	list.remove(2);
	list.print();
	cout << "the List count : ****************" << endl;
	cout << "the list contains " << list.count() << " elements" << endl;
	cout << "done " << endl;
	return 0;
}

practice makes perfect!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值