基于模板编程实现了一个泛型的链表,并通过函数实现了几个特定功能
简单估算了一下,去掉测试代码,大约200多行
链表类的属性如下:
- head: 头结点
- tail: 尾节点
- size: 节点个数
链表类约定如下:
链表没有空的头节点(哑节点)
链表尾节点tail的next属性赋值nullptr
当链表为空时,head和tail都赋值nullptr
当链表仅有一个元素时,head==tail
链表类的方法如下:
- empty(): 判断链表是否为空
- getSize(): 获取链表节点个数
- clear(): 清空链表
- display(): 显示链表所有元素
- front(): 返回链表头结点
- back(): 返回链表尾节点
- popFront(): 删除头节点
- popBack(): 删除尾节点
- pushFront(): 插入头节点
- pushBack(): 插入尾节点
另外,专门实现了如下函数:
- split(): 根据链表元素为奇数值还是偶数值,拆分链表
- findCommonElements(): 寻找两个链表的共有元素
- removeDuplicates(): 链表元素去重
- mergeAndDelete(): 合并两个链表,并对元素去重
- findKtyFromEnd(): 找到链表倒数第k个元素(作业要求不能使用尾节点)
以下是具体的代码实现:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <iostream>
using namespace std;
template<typename T>
struct Node {
T data;
Node* next;
Node(const T& newData) : data(newData), next(nullptr) {}
};
template<typename T>
class List {
public:
Node<T>* head;
Node<T>* tail;
int size;
List() : head(nullptr), tail(nullptr), size(0) {}
~List() { clear(); }
bool empty() const {
return head == nullptr;
}
int getSize() const {
return size;
}
void clear() {
while(!empty()) {
popFront();
}
}
void display() const {
Node<T>* cur = head;
while(cur != nullptr) {
cout<<cur->data<<" ";
cur = cur->next;
}
cout<<endl;
}
const T& front() const {
if(head == nullptr) cout<<"the list is empty"<<endl;
return head->data;
}
const T& back() const {
if(tail == nullptr) cout<<"the list is empty"<<endl;
return tail->data;
}
void popFront() {
if(empty()) return;
Node<T>* tmp = head;
head = head->next;
delete tmp;
if(head == nullptr) {
tail = nullptr;
}
size--;
}
void popBack() {
if(empty()) return;
if(head == tail) {
delete head;
head = tail = nullptr;
} else {
Node<T>* node = head;
while(node->next != tail)
node = node->next;
delete tail;
tail = node;
tail->next = nullptr;
}
size--;
}
void pushFront(const T& data) {
Node<T>* newNode = new Node<T>(data);
newNode->next = head;
head = newNode;
if(tail == nullptr) {
tail = newNode;
}
size++;
}
void pushBack(const T& data) {
Node<T>* newNode = new Node<T>(data);
if(tail == nullptr) {
head = newNode;
tail = newNode;
} else {
tail->next = newNode;
tail = tail->next;
}
size++;
}
};
#endif
void split(List<int>& L, List<int>& oddList, List<int>& evenList) {
Node<int>* cur = L.head;
while(cur != nullptr) {
if(cur->data % 2 == 1)
oddList.pushBack(cur->data);
else
evenList.pushBack(cur->data);
cur = cur->next;
}
}
template<typename T>
void findCommonElements(const List<T>& L1, const List<T>& L2, List<T>& L3) {
Node<T>* cur1 = L1.head;
Node<T>* cur2 = L2.head;
while(cur1 != nullptr && cur2 != nullptr) {
if(cur1->data == cur2->data) {
L3.pushBack(cur1->data);
cur1 = cur1->next;
cur2 = cur2->next;
} else if(cur1->data < cur2->data) {
cur1 = cur1->next;
} else {
cur2 = cur2->next;
}
}
}
template<typename T>
void removeDuplicates(List<T>& L) {
if(L.empty()) return;
Node<T>* cur = L.head;
while(cur->next != nullptr) {
if(cur->data == cur->next->data) {
Node<T>* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
} else {
cur = cur->next;
}
}
}
template<typename T>
void mergeAndDelete(List<T>& L1, List<T>& L2) {
Node<T>* cur1 = L1.head;
Node<T>* cur2 = L2.head;
Node<T>* pre1 = nullptr;
while(cur1 != nullptr && cur2 != nullptr) {
if(cur1->data < cur2->data) {
pre1 = cur1;
cur1 = cur1->next;
} else if(cur1->data == cur2->data) {
Node<T>* tmp = cur2;
cur2 = cur2->next;
delete tmp;
} else {
if(pre1 != nullptr) {
pre1->next = cur2;
} else {
L1.head = cur2;
}
pre1 = cur2;
cur2 = cur2->next;
pre1->next = cur1;
}
}
if(cur2 != nullptr) {
if(pre1 != nullptr) {
pre1->next = cur2;
} else {
L1.head = cur2;
}
}
//L2.clear();
L2.head = nullptr;
}
template<typename T>
bool findKthFromEnd(List<T>& L, int k, T& result) {
if(L.empty() || k <= 0) return false;
Node<T>* fast = L.head;
Node<T>* slow = L.head;
for(int i = 0; i < k - 1; ++i) {
if(fast->next != nullptr) {
fast = fast->next;
} else {
return false;
}
}
while(fast->next != nullptr) {
fast = fast->next;
slow = slow->next;
}
result = slow->data;
return true;
}