线性表(2)——双链表、循环链表

1.双链表

Line_Table_ADT.h

#pragma once
#ifndef LINE_TABLE_ADT_H
#define LINE_TABLE_ADT_H

//抽象基类
template <typename T>
class List
{
public:
	typedef T  Value_Type;
	typedef T* Value_Pointer;
	typedef T& Value_Reference;
	typedef const T& Const_Value_Reference;
private:
	void operator= (const List&) {}
	List(const List&) {}
public:
	//构造函数
	List() {}
	//析构函数
	virtual ~List() {}

	//纯虚函数子类必须去继承它吗?
	//清空线性表
	virtual void clear() = 0;
	//在当前位置插入
	virtual void insert(Const_Value_Reference element) = 0;
	//在线性表末尾添加
	virtual void append(Const_Value_Reference element) = 0;
	//移除当前位置的元素
	virtual Value_Type remove() = 0;
	//当前位置的前一个元素
	virtual void prev() = 0;
	//当前位置的下一个元素
	virtual void next() = 0;
	//线性表的长度
	virtual int length() const = 0;
	//当前位置
	virtual int currPos() const = 0;
	//当前位置元素的值
	virtual Const_Value_Reference getValue() = 0;     //思考返回一个常引用有什么好处?
	//移动到指定位置
	virtual void moveToPosition(int position) = 0;
};
#endif

Doubly_Link_List_Node.h

#pragma once
#ifndef DOUBLY_LINK_LIST_NODE
#define DOUBLY_LINK_LIST_NODE
template <typename T>
class Doubly_Link_List_Node
{
public:
	typedef T Value_Type;
	typedef T& Value_Reference;
	typedef const T& Const_Value_Reference;
	typedef T* Value_Pointer;
	typedef Doubly_Link_List_Node  Node;
	typedef Doubly_Link_List_Node*  Node_Pointer;
	typedef Doubly_Link_List_Node* Prev_Pointer;
	typedef Doubly_Link_List_Node* Next_Pointer;
	typedef Doubly_Link_List_Node* Node_Pool;
private:
	static Node_Pool node_Pool;
public:
	Value_Type value;
	Prev_Pointer prev;
	Next_Pointer next;

	//有参构造
	Doubly_Link_List_Node(Const_Value_Reference m_value,
							Prev_Pointer m_prev, 
							Next_Pointer m_next)
		:value(m_value), prev(m_prev), next(m_next)
	{}

	//默认构造
	Doubly_Link_List_Node(Prev_Pointer m_prev = nullptr, Next_Pointer m_next = nullptr)
		:prev(m_prev), next(m_next)
	{}

	//**************使用内存池技术改善效率************
	//重载new和delete
	void* operator new(size_t) 
	{
		//内存池中没有申请到结点内存时,调用全局的new申请内存直接返回
		if (node_Pool == nullptr)
			return ::new Node;
		//内存池中有结点时
		Node_Pointer temp = node_Pool;
		//从内存池中申请后,内存池中结点减少,即内存池首地址的指向下一个结点区域
		node_Pool = node_Pool->next;
		return temp;
	}

	void operator delete(void* free_node)
	{
		//释放结点内存直接将结点释放到内存池中

		//每释放一个都插入到内存池的头部
		//让释放的结点指向内存池首地址
		((Node_Pointer)free_node)->next = node_Pool;
		//让内存池的首地址指向释放的结点
		node_Pool = (Node_Pointer)free_node;
	}
};
template <typename T>
Doubly_Link_List_Node<T>* Doubly_Link_List_Node<T>::node_Pool = nullptr;
#endif 

Doubly_Link_List.h

#pragma once
#include "Line_Table_ADT.h"
#include "Doubly_Link_List_Node.h"
#include<iostream>
#include<string>

template <typename T>
class Doubly_Link_List :public List<T>
{
public:
	typedef Doubly_Link_List_Node<T>  Node;
	typedef Doubly_Link_List_Node<T>* Node_Pointer;
	typedef Doubly_Link_List_Node<T>* Head_Pointer;
	typedef Doubly_Link_List_Node<T>* Tail_Pointer;
	typedef Doubly_Link_List_Node<T>* Current_Pointer;

	typedef T Value_Type;
	typedef const T&  Const_Value_Reference;
private:
	Head_Pointer head;
	Tail_Pointer tail;
	Current_Pointer curr;
	int list_Length;

	//初始化的函数,只用于此类,不提供对外接口
	void init()
	{
		head = tail = curr = new Node;
		list_Length = 0;
	}

	void removeAll()
	{
		while (head != nullptr)
		{
			curr = head;
			head = head->next;
			delete curr;
		}
	}

	//满足某种异常条件,抛出异常,打印错误信息
	void judge_OutOfRange(bool condition, const std::string& printInfo)
	{
		try
		{
			if (condition)
			{
				throw condition;
			}
		}
		catch (bool)
		{
			std::cerr << printInfo << std::endl;   //为什么不要在.h文件中使用using namespace std?
			exit(1);
		}
	}
public:
	Doubly_Link_List()
	{
		init();
	}
	~Doubly_Link_List()
	{
		removeAll();
	}

	void clear() override
	{
		removeAll();
		init();
	}

	void insert(Const_Value_Reference value) override
	{
		Node_Pointer temp = new Node;
		::new(temp)Node(value, curr,curr->next);
		if (curr == tail)
			tail = temp;
		else
			curr->next->prev = temp;

		curr->next = temp;
		list_Length++;
	}

	void append(Const_Value_Reference value) override
	{
		Node_Pointer temp = new Node;
		::new(temp)Node(value, tail, tail->next);
		tail->next = temp;
		tail = temp;
		list_Length++;
	}

	Value_Type remove() override
	{
		//判断链表是否为空
		judge_OutOfRange(head->next == nullptr, "Link_List is none!");

		Value_Type return_value = curr->next->value;

		Node_Pointer temp = curr->next;
		if (tail == curr->next)
			tail = curr;
		else
			temp->next->prev = curr;

		curr->next = temp->next;

		delete temp;
		list_Length--;

		return return_value;
	}

	void prev() override
	{
		curr = curr->prev;
	}

	void next() override
	{
		curr = curr->next;
	}

	int length() const
	{
		return list_Length;
	}

	Const_Value_Reference getValue() 
	{
		return curr->next->value;
	}

	int currPos()const override
	{
		Node* temp = head;
		int i;
		for (i = 0; temp != curr; i++)
		{
			temp = temp->next;
		}
		return i;
	}

	void moveToPosition(int position) override
	{
		judge_OutOfRange((position < 0 || position >= list_Length), "Position is out of range!");
		curr = head;
		for (int i = 0; i < position; i++)
			curr = curr->next;
	}
	void print()
	{
		for (int i = 0; i < length(); i++)
		{
			moveToPosition(i);
			std::cout << getValue() << std::endl;
		}
	}
};

main.cpp

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

using namespace std;

int main()
{
	Doubly_Link_List<int> test_link_list;

	cout << "测试insert和append函数" << endl;
	test_link_list.insert(5);
	test_link_list.insert(100);
	test_link_list.insert(300);
	test_link_list.append(400);
	test_link_list.append(500);
	test_link_list.print();

	cout << "\n测试remove函数" << endl;
	cout << "被删除的元素的值为:" << test_link_list.remove() << endl;
	test_link_list.print();


	cout << "\n测试prev、next、currPos" << endl;
	cout << "当前指针位置为:" << test_link_list.currPos() << endl;
	test_link_list.prev();
	test_link_list.prev();
	cout << "前移两次指针位置为:" << test_link_list.currPos() << endl;
	test_link_list.next();
	cout << "后移一次指针位置为:" << test_link_list.currPos() << endl;

	cout << "\n测试length" << endl;
	cout << "当前顺序表的长度为:" << test_link_list.length() << endl;

	cout << "\n测试clear" << endl;
	test_link_list.clear();
	cout << "当前顺序表的长度为:" << test_link_list.length() << endl;
	test_link_list.append(500);
	cout << "当前顺序表的长度为:" << test_link_list.length() << endl;
	test_link_list.print();
}

运行结果: 

2.循环链表

循环链表的C++实现(有头指针和尾指针的单链表实现)

Single_Link_List_Node.h

#pragma once
#ifndef SINGLE_LINK_LIST_NODE
#define SINGLE_LINK_LIST_NODE

template <typename T>
class Single_Link_List_Node
{
public:
	typedef T  Value_Type;
	typedef T* Value_Pointer;
	typedef T& Value_Reference;
	typedef const T& Const_Value_Reference;
	typedef Single_Link_List_Node  Node;
	typedef Single_Link_List_Node*  Node_Pointer;
	typedef const Single_Link_List_Node&  Const_Node_Reference;
	typedef Single_Link_List_Node* Next_Pointer;
	typedef Node* Node_Pool;

private:
	static  Node_Pool node_Pool;  //声明为static变量,让所有对象共享
public:
	Value_Type value;   //结点存储的值
	Next_Pointer next;  //结点保存的指向下一个结点的指针

	//结点构造函数,创建结点,对应C语言实现的create函数
	Single_Link_List_Node(Const_Value_Reference m_value, Next_Pointer m_next = nullptr)
		:value(m_value), next(m_next)
	{
	}
	//默认构造函数
	//为头指针,尾指针,当前指针的定义提供不用没有值的构造方法
	Single_Link_List_Node(Next_Pointer m_next = nullptr)
	{}

	//重载new运算符
	void* operator new(size_t)
	{
		//内存池中没有申请到结点内存时,调用全局的new申请内存直接返回
		if (node_Pool == NULL)
			return ::new Node;
		//内存池中有结点时
		Node_Pointer temp = node_Pool;
		//从内存池中申请后,内存池中结点减少,即内存池首地址的指向下一个结点区域
		node_Pool = node_Pool->next;
		return temp;
	}

	//重载delete运算符
	void operator delete(void* free_node)
	{
		//释放结点内存直接将结点释放到内存池中

		//每释放一个都插入到内存池的头部
		//让释放的结点指向内存池首地址
		((Node_Pointer)free_node)->next = node_Pool;
		//让内存池的首地址指向释放的结点
		node_Pool = (Node_Pointer)free_node;
	}

	bool operator==(Const_Node_Reference node)
	{
		if (value == node.value && next == node.next)
			return true;
	}
};

//类的静态变量的初始化
template <typename T>
Single_Link_List_Node<T>* Single_Link_List_Node<T>::node_Pool = nullptr;
#endif 

Circular_Linked.h

#pragma once
#ifndef CIRCULAR_LINKED_LIST_H
#define CIRCULAR_LINKED_LIST_H
#include "Single_Link_List_Node.h"
#include<iostream>
#include <string>
template<typename T>
class Circular_Linked_List
{
public:
	typedef T Value_Type;
	typedef const T&  Const_Value_Reference;

	typedef Single_Link_List_Node<T> Node;
	typedef Single_Link_List_Node<T>* Node_Pointer;
	typedef Single_Link_List_Node<T>* Head;
	typedef Single_Link_List_Node<T>* Tail;
	typedef Single_Link_List_Node<T>* Curr;
private:
	Head head;
	Tail tail;
	Curr curr;

	int size;

	//初始化的函数,只用于此类,不提供对外接口
	void init()
	{
		head = tail = curr = new Node;
		size = 0;
	}

	void removeAll()
	{
		while (head->next !=head )
		{
			curr = head;
			head = head->next;
			tail->next = head;
			delete curr;
		}
		delete head;
		size = 0;
	}

	//满足某种异常条件,抛出异常,打印错误信息
	void judge_OutOfRange(bool condition, const std::string& printInfo)
	{
		try
		{
			if (condition)
			{
				throw condition;
			}
		}
		catch (bool)
		{
			std::cerr << printInfo << std::endl;   //为什么不要在.h文件中使用using namespace std?
			exit(1);
		}
	}
public:
	//构造函数
	Circular_Linked_List()
	{
		init();
	}

	//析构函数
	~Circular_Linked_List()
	{
		removeAll();
	}

	void clear()
	{
		removeAll();
		init();
	}
	//插入
	void insert(Const_Value_Reference value) 
	{
		if (head->next == nullptr)
		{
			
			tail = new Node;			//使用operator new分配内存
			::new(tail)Node(value, tail);
			head->next = tail;
		}
		else
		{
			Node* temp = curr->next;
			curr->next = new Node;			//使用operator new分配内存
			::new(curr->next)Node(value, temp);
			if (curr == head)
			{
				tail->next = curr->next;
			}
			else if (curr == tail)				//记得判断尾节点的特殊情况
			{
				tail = curr->next;
			}
		}
		size++;

	}

	void append(Const_Value_Reference value) 
	{
		if (head->next == nullptr)
		{

			tail = new Node;			//使用operator new分配内存
			::new(tail)Node(value, tail);
			head->next = tail;
		}
		else
		{
			tail->next = new Node(value, tail->next);
			tail = tail->next;
		}
		size++;
	}


	//移除
	Value_Type remove() 
	{
		//判断链表是否为空
		judge_OutOfRange((head->next == nullptr), "Link_List is none!");

		Value_Type remove_value = curr->next->value;
		Node* temp = curr->next;
		if (tail->next == tail)
		{
			head = curr = nullptr;
			
		}
		else if (tail->next != tail && curr == head)
		{
			curr->next = curr->next->next;
			tail->next = curr->next;
		}
		else if (tail->next != tail && curr == tail)
		{
			curr->next = curr->next->next;
			head->next= curr->next;
		}
		else
		{
			curr->next = curr->next->next;
		}
		delete  temp;
		size--;

		return remove_value;
	}

	void prev() 
	{
		if (curr == head)
			return;
		Node* temp = head;
		while (temp->next != curr)
			temp = temp->next;
		curr = temp;
	}

	void next() 
	{
			curr = curr->next;
	}

	int length() const
	{
		return size;
	}

	Const_Value_Reference getValue()  
	{
		//判断链表是否为空
		judge_OutOfRange((head->next == nullptr), "Link_List is none!");
		return curr->next->value;
	}

	int currPos()const 
	{
		Node* temp = head;
		int i;
		for (i = 0; temp != curr; i++)
		{
			temp = temp->next;
		}
		return i;
	}

	void moveToPosition(int position) 
	{
		if(size!=0)
			judge_OutOfRange((position < 0 || position >= size), "Position is out of range!");
		curr = head;
		for (int i = 0; i < position; i++)
			curr = curr->next;
	}

	//遍历打印
	void print()
	{
		for (int i = 0; i < length(); i++)
		{
			moveToPosition(i);
			std::cout << getValue() << std::endl;
		}
	}

};
#endif 

main.cpp

#include "pch.h"
#include <iostream>
#include "Circular_Linked_List.h"

using namespace std;

int main()
{
	Circular_Linked_List<int> test_link_list;

	cout << "测试insert和append函数" << endl;
	test_link_list.insert(5);
	test_link_list.insert(100);
	test_link_list.insert(300);
	test_link_list.append(400);
	test_link_list.append(500);
	test_link_list.print();

	cout << "\n测试remove函数" << endl;
	cout << "被删除的元素的值为:" << test_link_list.remove() << endl;
	test_link_list.print();


	cout << "\n测试prev、next、currPos" << endl;
	cout << "当前指针位置为:" << test_link_list.currPos() << endl;
	test_link_list.prev();
	test_link_list.prev();
	cout << "前移两次指针位置为:" << test_link_list.currPos() << endl;
	test_link_list.next();
	cout << "后移一次指针位置为:" << test_link_list.currPos() << endl;

	cout << "\n测试length" << endl;
	cout << "当前顺序表的长度为:" << test_link_list.length() << endl;

	cout << "测试循环" << endl;
	test_link_list.moveToPosition(0);
	cout << test_link_list.getValue() << endl;
	test_link_list.next();

	cout << test_link_list.getValue() << endl;
	test_link_list.next();

	cout << test_link_list.getValue() << endl;
	test_link_list.next();

	cout << test_link_list.getValue() << endl;
	test_link_list.next();

	cout << test_link_list.getValue() << endl;
	test_link_list.next();

	cout << test_link_list.getValue() << endl;
	test_link_list.next();

	cout << test_link_list.getValue() << endl;
	test_link_list.next();

	cout << test_link_list.getValue() << endl;
	test_link_list.next();

	cout << test_link_list.getValue() << endl;
	test_link_list.next();
	

	cout << "\n测试clear" << endl;
	test_link_list.clear();
	cout << "当前顺序表的长度为:" << test_link_list.length() << endl;
	test_link_list.append(500);
	cout << "当前顺序表的长度为:" << test_link_list.length() << endl;
	test_link_list.print();

	
}

运行结果:

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值