双向链表版Vector容器(自实现代码)

Vector.h

#pragma once
#include<iostream>
#include"errTooBigException.h"
#include"errTooSmallException.h"

using namespace std;

class errSizeException;//下标越界异常类
class errTooBigException;//下标过大类,为errSizeException的子类
class errTooSmallException;//下标过小类,为errSizeException的子类


template <typename T>
struct List_Node {//定义泛型结构体
	T data;
	List_Node* pre;
	List_Node* next;
};

template <typename T>
class Vector
{
public:
	Vector();
	~Vector();
	Vector(const Vector<T>& v2);

	int size()const;//获取容器的保存元素个数

	bool push_back(T& t);//将元素插入到链表的尾部
	bool pop_back();//将链表的最后一个元素删除

	bool erase(unsigned int loc);//删除指定位置的元素
	bool isEmpty()const;//判断容器是否为空
	bool clear();//清空容器

	bool Get_front(T& data)const;//获取容器的第一个元素
	bool Get_rear(T& data)const;//获取容器的最后一个元素

	T& operator[](int loc);//重载下标运算符
	Vector<T>& operator=(const Vector<T>& v2);//重载赋值运算符

	template <typename T>
	friend ostream& operator<<(ostream& os, const Vector<T>& v2);//重载输出运算符

private:

	T& Search_data_pos(int loc);//搜索指定位置的元素

	bool Ini_List();//初始化链表
	bool Insert_List_back(T &t);//在链表尾部添加元素
	bool Delete_List_back();//删除链表尾部的元素
	bool Delete_List_pos(unsigned int loc);//删除指定位置的元素
	bool Destroy_List();//销毁链表
	bool isEmty_List()const;//判断链表是否为空
	bool Copy_List(const Vector<T>& v2);//拷贝另一个链表
	
	List_Node<T>* List;//链表头
	List_Node<T>* rear;//链表尾
	int length;//保存元素的个数
};

Vector.hpp

#include "Vector.h"

template <typename T>
Vector<T>::Vector() {
	cout << __FUNCTION__ << endl;//打印出函数名
	Ini_List();//初始化双向链表
}

template <typename T>
Vector<T>::~Vector() {
	cout << __FUNCTION__ << endl;
	Destroy_List();//释放动态申请的内存
}

template <typename T>
Vector<T>::Vector(const Vector<T>& v2) {
	cout<<"\n调用拷贝构造函数\n";
	Copy_List(v2);//拷贝另一个链表
}

template <typename T>
int Vector<T>::size()const {
	return length;
}

template <typename T>
bool Vector<T>::Ini_List() {
	List = nullptr;
	rear = nullptr;
	return true;
}

template <typename T>
bool Vector<T>::isEmty_List()const{
	if (length == NULL)
		return true;
	return false;
}

template <typename T>
bool Vector<T>::Insert_List_back(T& t) {

	List_Node<T> * New_node = nullptr;
	New_node = new List_Node<T>;
	if (!New_node) return false;//如果分配内存失败,返回false;

	if (isEmty_List()) {//如果此时链表为空
		List = rear= New_node;
		New_node->pre = nullptr;
	}
	else {
		rear->next = New_node;
		New_node->pre = rear;
		rear = New_node;
	}
	New_node->next = nullptr;
	New_node->data = t;

	++length;//双向链表长度加一

	return true;
}

template <typename T>
bool Vector<T>::Delete_List_back() {//删除链表尾部的元素

	if (isEmty_List()) return false;//如果双向链表为空,返回false;

	List_Node<T>* End_node = rear;//调整指针域
	if(rear->pre)
	rear->pre->next = nullptr;
	if(rear)
	rear = rear->pre;

	delete End_node;
	--length;//删除后链表长度减一

	return true;
}

template <typename T>
bool Vector<T>::Delete_List_pos(unsigned int loc) {//删除指定位置的元素
	if (isEmty_List()||loc >= length) return false;
	List_Node<T>* de_Node = List;
	
	for (int i = 0; i < loc; i++) {//找到删除节点的位置
			de_Node = de_Node->next;
	}

	if(de_Node->next)//只有在链表删除元素的下一个不为空的情况下调整删除元素的下一个的指针域
	de_Node->next->pre = de_Node->pre;
	if (de_Node->pre)//只有在链表删除元素的前一个不为空的情况下调整删除元素的前一个的指针域
	de_Node->pre->next = de_Node->Next;

	delete de_Node;
	--length;//删除后链表长度减一

	if (isEmty_List()) {//如果删除节点后链表变为空的话,将头指针和尾指针置为空
		List = rear = nullptr;
	}

	return true;
}

template <typename T>
bool Vector<T>::Destroy_List() {//销毁链表
	if (isEmty_List()) return false;//如果双向链表为空,返回false;

	List_Node<T>* de_Node = List;
	while (de_Node){
		List = List->next;
		delete de_Node;
		de_Node = List;
	}

	length = NULL;
	List = nullptr;
	rear = nullptr;
	cout << __FUNCTION__ << endl;
	return true;
}

template <typename T>
bool Vector<T>::push_back(T& t) {
	if (Insert_List_back(t)) return true;
	return false;
}

template <typename T>
bool Vector<T>::pop_back() {
	if (Delete_List_back()) return true;
	return false;
}

template <typename T>
bool Vector<T>::clear() {
	if (Destroy_List()) return true;
	return false;
}


template <typename T>
bool Vector<T>::erase(unsigned int loc) {
	if (Delete_List_pos(loc)) return true;
	return false;
}

template <typename T>
bool Vector<T>::isEmpty()const {
	if(isEmty_List())return true;
	return false;
}

template <typename T>
bool Vector<T>::Get_front(T& data)const {
	if (isEmty_List())return false;
	data = List->data;
	return true;
}

template <typename T>
bool Vector<T>::Get_rear(T& data)const {
	if (isEmty_List())return false;
	data=rear->data;
	return true;
}

template <typename T>
bool Vector<T>::Copy_List(const Vector<T>& v2) {//拷贝另一个链表
	if (v2.isEmpty()) return false; 
	List_Node<T>* New_node = nullptr;
	List_Node<T>* Temp_node = v2.List;
	for (int i = 0; i < v2.length; i++) {
		New_node = new List_Node<T>;
		if (!New_node) return false;
		New_node->data = Temp_node->data;
		if (i == 0) {
			List = rear = New_node;
			New_node->pre = nullptr;
		}
		else {	
			New_node->pre = rear;
			rear->next= New_node;
			rear = New_node;
		}
		New_node->next = nullptr;
		Temp_node = Temp_node->next;
	}
	length = v2.length;
	return true;
}

template <typename T>
T& Vector<T>::operator[](int loc){
	try {
		T& data=Search_data_pos(loc);
		return data;
	}
	catch (errSizeException * Err) {//这里利用C++多态的特性,当父类的指针指向子类的对象时,调用的是子类的what方法
		Err->what();
		delete Err;
	}
	catch (...) {
		cout << "出现未知错误!" << endl;
	}
}

template <typename T>
T& Vector<T>::Search_data_pos(int loc) {
	if (loc >= length) {
		cout << "loc=" << loc << endl;
		errSizeException* errSizeException = new errTooBigException;
		throw errSizeException;//下标过大,抛出下标过大类对象的指针
	}
	else if (loc < 0) {
		cout << "loc=" << loc << endl;
		errSizeException* errSizeException = new errTooSmallException;
		throw errSizeException;//下标过小,抛出下标过小类对象的指针
	}
	List_Node<T>* Temp_node = List;
	for (int i = 0; i < loc; i++) {
		Temp_node = Temp_node->next;
	}
	return Temp_node->data;
}

template <typename T>
Vector<T>& Vector<T>::operator=(const Vector<T>& v2) {
	Copy_List(v2);
	return *this;
}

template <typename T>
ostream& operator<<(ostream& os, const Vector<T>& v2) {
	List_Node<T>* Temp = v2.List;
	while (Temp) {
		os << Temp->data << endl;
		Temp = Temp->next;
	}
	return os;
}

errSizeException.h

#pragma once
class errSizeException
{
public:
	errSizeException();
	virtual ~errSizeException();//这里要将析构函数改为虚析构函数,否则在析构子类对象的时候会不会调用父类的析构函数
	virtual void what();
};

errSizeException.cpp

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

errSizeException::errSizeException()
{
}

errSizeException::~errSizeException()
{
}

void errSizeException::what()
{
	std::cout << "Vector容器发生越界!" << std::endl;
}

errTooSmallException.h

#pragma once
#include "errSizeException.h"
class errTooSmallException final:public errSizeException //final在这里使用使得errTooSmallException类不能被继承
{
public:
	errTooSmallException();
	~errTooSmallException();
	void what() final override;//final在这里使用使得what()不能被子类所重写
};

errTooSmallException.cpp

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

errTooSmallException::errTooSmallException():errSizeException(){
}

errTooSmallException::~errTooSmallException(){
}

void errTooSmallException::what()
{
	std::cout << "下标太小,导致Vector容器越界!" << std::endl;
}

errTooBigException.h

#pragma once
#include "errSizeException.h"
class errTooBigException :public errSizeException{
public:
	   errTooBigException();
	  ~errTooBigException();
	  void what()final override;
};

errTooBigException.cpp

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

errTooBigException::errTooBigException():errSizeException(){

}

errTooBigException::~errTooBigException(){

}

void errTooBigException::what(){
	std::cout << "下标太大,Vector容器发生越界!" <<std::endl;
}

测试用的Student类
Student.h

#pragma once
#include<iostream>

using namespace std;

class Student
{
public:
	Student();
	Student(char *other_pname,int age);
	Student(const Student& stu);
	~Student();
	Student& operator=(const Student& stu2);
private:
	char* pname;
	int age;
	friend ostream& operator<<(ostream& os, const Student& stu);
};

Student.cpp

#include<string.h>
#include "Student.h"


Student::Student(){
    pname =nullptr;
    age = 0;
}

Student::Student(char* other_pname, int age){
	int len = strlen(other_pname);
    pname = new char[len+1];
    strcpy_s(pname,len+1, other_pname);
    this->age = age;
}

Student::Student(const Student& stu){
    if (pname)
        delete pname;

    int len = strlen(stu.pname);
    pname = new char[len + 1];
    strcpy_s(pname, len+1, stu.pname);
    this->age =stu.age;
}

Student::~Student()
{
    delete this->pname;
}

Student& Student::operator=(const Student& stu2)
{
    cout << __FUNCTION__ << endl;
    if (this->pname)
        delete this->pname;
    int len = strlen(stu2.pname);
    this->pname = new char[len + 1];
    strcpy_s(this->pname,len+1,stu2.pname);
    this->age = stu2.age;
    return *this;
}


ostream& operator<<(ostream& os, const Student& stu){
    os << "[姓名]:" << stu.pname << "\t[年龄]:" << stu.age;
    return os;
}

test.cpp

#include<iostream>
#include<windows.h>
#include<string>
#include"Student.h"
#include"Vector.hpp"


using namespace std;


int main(void) {
	{
		char name[] = {"李四"};
		Student stu1(name,20);
		char name2[] = { "张三" };
		Student stu2(name2,22);

		Vector<Student> v1;
		
		v1.push_back(stu1);
		v1.push_back(stu2);


		cout << "长度为:";
		cout << v1.size() << endl;

		v1[-1];

		Student temp;

		cout<<"v1容器中的元素为:"<<endl;
		cout << v1 << endl;

		v1.Get_rear(temp);
		cout <<"尾元素为"<< temp << endl;
		v1.pop_back();
		v1.Get_rear(temp);
		cout << "删除尾元素后,新的尾元素为:" << temp << endl;
		
		Vector<int> v2;
		for (int i = 10; i < 20; i++) {
			v2.push_back(i);
		}
		cout << v2 << endl;
	}
	system("pause");
	return EXIT_SUCCESS;
}

运行结果为
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值