单链表 ( 数据结构 )

定义

  1. 链表的节点
/**
 *  @brief 单链表的节点
 *  @tparam T  节点元素类型(class类型比较适用)
 */
template <class T>
class Node {
public:
	T val;
	Node* next;
	Node() = default;
	Node(const T& t, Node* nxt = nullptr) : val(t), next(nxt) {}
};
  1. 链表
/**
 *  @brief 头节点不为空的单链表
 *  @tparam T  节点元素类型(class类型比较适用)
 */
template <class T>
class LinkedList {
private:
	Node<T>* __head;
	Node<T>* __tail;
	unsigned __size;

public:
	/**
	 * 初始化
	 */
	LinkedList() : __head(nullptr), __tail(nullptr), __size(0) {}
	/**
	 * 初始化
	 * @param a 数组
	 * @param n 长度
	 */
	LinkedList(T* a, int n);
	/**
	 * 头插
	 * @param t 待插元素
	 */
	void insertHead(const T& t);
	/**
	 * 尾插
	 * @param t 待插元素
	 */
	void insertTail(const T& t);
	/**
	 * 按下标插入
	 * @param i 下标
	 * @param t 待插元素
	 */
	void insert(unsigned i, const T& t);
	/**
	 * 移除头节点
	 * @return 被移除的节点值
	 */
	T removeHead();
	/**
	 * 移除尾节点
	 * @return 被移除的节点值
	 */
	T removeTail();
	/**
	 * 移除元素
	 * @param t 待语移除的元素
	 * @return true 元素存在, 否则false
	 */
	bool remove(const T& t);
	/**
	 * 判断链表是否为空
	 * @return true空, 否则false
	 */
	bool empty() { return __size == 0 ? true : false; }
	/**
	 * 获取链表长度
	 * @return size
	 */
	unsigned size() { return __size; }
	/**
	 * 链表反转
	 */
	void reverse();
	/**
	 * 链表部分反转 { 0 -> i } , 下标从零开始
	 * @param i 起始节点下标(包括)
	 * @throws Exception : Index out of range !
	 */
	void reverse(unsigned i);
	/**
	 * 链表部分反转 { i -> j } , 下标从零开始
	 * @param i 起始节点下标(包括)
	 * @param j 结束节点下标(包括)
	 * @throws Exception : Index out of range !
	 */
	void reverse(unsigned i, unsigned j);
	/**
	 * 由t获取元素的下标(从零开始)
	 * @param t 待查找元素
	 * @return 下标 或者 -1
	 * @throws Exception : Empty List :(
	 */
	int indexOf(T t);
	/**
	 * 由下标获取元素
	 * @param index 下标
	 * @return 下标对应得元素
	 * @throws Exception : Index out of range !
	 */
	T at(int index);
	/**
	 * 删除链表, 释放空间
	 */
	~LinkedList();
	/**
	 * 将链表元素输出到标准流
	 * @param os 标准输出流对象
	 * @param l 链表对象
	 * @return 标准输出流对象
	 */
	template <class U>
	friend std::ostream& operator<<(std::ostream& os, const LinkedList<U>& l);
};

实现

template <class T>
LinkedList<T>::LinkedList(T* a, int n) {
	LinkedList();
	for (; --n != -1;)
		insertTail(a[n]);
}
template <class T>
void LinkedList<T>::insertHead(const T& t) {
	Node<T>* node = new Node<T>(t);
	if (__head == nullptr) {
		__head = node;
		__tail = __head;
	}
	else {
		node->next = __head;
		__head = node;
	}
	++__size;
}
template <class T>
void LinkedList<T>::insertTail(const T& t) {
	Node<T>* node = new Node<T>(t);
	if (__tail == nullptr) {
		__tail = node;
		__head = __tail;
	}
	else {
		__tail->next = node;
		__tail = __tail->next;
	}
	++__size;
}
template <class T>
void LinkedList<T>::insert(unsigned i, const T& t) {
	Node<T>* node = new Node<T>(t);
	// 没有元素或i>__size
	if (__head == nullptr || i > __size) {
		insertTail(t);
		return;
	}
	if (i == 0) {
		insertHead(t);
		return;
	}
	Node<T>*pre = nullptr, *p = __head;
	// 从零开始
	while (--i) {
		pre = p;
		p = p->next;
	}
	// 更新__tail
	node->next = p;
	pre->next = node;
	++__size;
}
template <class T>
T LinkedList<T>::removeHead() {
	if (__size == 0)
		throw "Exception : Remove form an empty List :(";
	--__size;
	Node<T>* p = __head;
	T ret = std::move(p->val);
	__head = __head->next;
	delete p;
	return ret;
}
template <class T>
T LinkedList<T>::removeTail() {
	if (__size == 0)
		throw "Exception : Remove form an empty List :(";
	--__size;
	Node<T>* p = __head;
	for (Node<T>* i = __head; i->next != nullptr; i = i->next)
		p = i;
	if (p == __head) { // 第一个
		T t = __head->val;
		delete __head;
		__head = nullptr;
		__tail = nullptr;
		return t;
	}
	Node<T>* node = p->next;
	T ret = std::move(node->val);
	p->next = nullptr;
	__tail = p;
	delete node;
	return ret;
}
template <class T>
bool LinkedList<T>::remove(const T& t) {
	if (__size == 0)
		throw "Exception : Remove form an empty List :(";
	Node<T>* p = __head;
	Node<T>* i = __head;
	// 要删的前一个
	for (; i != nullptr && i->val != t; i = i->next) {
		p = i;
	}
	if (i == nullptr) { // 没有
		return false;
	}
	if (p == __head) { // 第一个
		removeHead();
		return true;
	}
	Node<T>* node = p->next;
	p->next = node->next;
	delete node;
	--__size;
	return true;
}
template <class T>
void LinkedList<T>::reverse() {
	__tail = __head;
	for (Node<T>*p = __head->next, *pre = __head; p; pre->next = p) {
		Node<T>* node = p;
		p = p->next;
		node->next = __head;
		__head = node;
	}
}
template <class T>
void LinkedList<T>::reverse(unsigned i) {
	if (i < 0 || i >= __size)
		throw "Exception : Index out of range !";
	if (i == __size) {
		reverse();
		return;
	}
	Node<T>*tail = __head, *head = __head;
	for (int k = 0; k < i; ++k) {
		tail = tail->next;
	}
	for (Node<T>*p = __head->next, *pre = __head; p != tail; pre->next = p) {
		Node<T>* node = p;
		p = p->next;
		node->next = __head;
		__head = node;
	}
	head->next = tail;
}
template <class T>
void LinkedList<T>::reverse(unsigned i, unsigned j) {
	if (i < 0 || i > j || j >= __size)
		throw "Exception : Index out of range !";
	if (i == j)
		return;
	if (i == 0) {
		reverse(j);
		return;
	}
	Node<T>*pre = __head, *s, *p = pre->next, *next = nullptr;
	int k = 1;
	for (; k < i; ++k) { // find start
		pre = p;
		p = p->next;
	}
	for (; k < j; ++k) // find end
		p = p->next;
	next = p->next;
	p = pre->next;
	k = j - i + 1; // 操作次数
	for (; k--;) { // 如法炮制
		Node<T>* node = p;
		p = p->next;
		node->next = next;
		next = node;
	}
	pre->next = next;
}
template <class T>
int LinkedList<T>::indexOf(T t) {
	if (__head == nullptr)
		throw "Exception : Empty List :(";
	int index = 0;
	for (Node<T>* p = __head; p != nullptr; p = p->next) {
		if (p->val == t)
			return index;
		++index;
	}
	return -1;
}
template <class T>
T LinkedList<T>::at(int i) {
	if (i < 0 || i >= __size)
		throw "Exception : Index out of range !";
	Node<T>* p = __head;
	for (; i--;)
		p = p->next;
	return p->val;
}
template <class T>
LinkedList<T>::~LinkedList() {
	while (__head != nullptr) {
		Node<T> p = __head;
		__head = __head->next;
		delete p;
	}
	__tail = nullptr;
}
template <class U>
std::ostream& operator<<(std::ostream& os, const LinkedList<U>& l) {
	if (l.__head != nullptr)
		for (Node<U>* i = l.__head; i != nullptr; i = i->next) {
			os << i->val << " ";
		}
	else
		os << "null ";
	return os;
}

测试

#include "LinkedList.h"
using namespace std;
LinkedList<string>* ll;
void init() {
	cout << "----\n初始化\n";
	ll = new LinkedList<string>();
	ll->insertHead("Quanwei");
	ll->insertHead("Tang");
	ll->insertHead("Hi");
	ll->insertTail("Hello");
	ll->insertTail("Linked");
	ll->insertTail("List");
	ll->insertTail("Node");
	cout << "init: " << *ll << "\n";
}
void testInsert() {
	cout << "----\n插入测试:\n";
	ll->insert(0, "芜湖~");
	cout << "insert: \n"
		 << *ll << "\n";
	ll->insert(0, "芜湖~");
	cout << "insert: \n"
		 << *ll << "\n";
	ll->insert(ll->size(), "尾巴前面一个~");
	cout << "insert: \n"
		 << *ll << "\n";
	ll->insert(ll->size() + 1, "尾巴后面一个~");
	cout << "insert: \n"
		 << *ll << "\n";
	ll->insert(100, "ll->insert(100, \"\");");
	cout << "insert: \n"
		 << *ll << "\n";
	ll->insert(-100, "ll->insert(-100, \"\");");
	cout << "insert: \n"
		 << *ll << "\n";
}
void testIndexOf() {
	cout << "----\n测试获取元素下标: \n";
	cout << "ll->indexOf(\"ll->insert(-100, \"\");\")\t" << ll->indexOf("ll->insert(-100, \"\");") << '\n';
	cout << "ll->indexOf(\"芜湖~\")\t" << ll->indexOf("芜湖~") << '\n';
}
void testAt() {
	cout << "----\n测试通过下标获取: \n";
	cout << "at(0): " << ll->at(0) << '\n';
	cout << "at(size-1): " << ll->at(ll->size() - 1) << '\n';
}
void testReverse() {
	cout << "----\n测试数组反转: \n";
	ll->reverse();
	cout << "全部反转后: \n"
		 << *ll << '\n';
	ll->reverse(5);
	cout << "反转 [0, 5] 后: \n"
		 << *ll << '\n';
	ll->reverse(2, ll->size() - 2);
	cout << "反转 [2, ll->size()-2] 后: \n"
		 << *ll << '\n';
}
void testRemove() {
	cout << "----\n测试移除元素: \n";
	cout << "removeHead: " << ll->removeHead() << '\n';
	cout << "removeTail: " << ll->removeTail() << '\n';
	cout << "remove(\" Tang \"): " << (ll->remove("Tang") ? "true" : "false") << '\n';
	cout << "remove(\" Tang \"): " << (ll->remove("Tang") ? "true" : "false") << '\n';
	cout << "移除后: " << *ll << '\n';
}
void testException() {
	try {
		cout << "at(-1): ";
		cout << ll->at(-1) << '\n';
	}
	catch (const char* e) {
		std::cerr << e << '\n';
	}
}
int main(int argc, char const* argv[]) {
	init();
	testInsert();
	testIndexOf();
	testAt();
	testReverse();
	testRemove();
	testException();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SVIP_Quanw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值