#include <iostream>
using namespace std;
template<class T>
struct Node {
T data;
Node <T>* next;
};
template<class T>class LinkedList {
private:
Node <T>* front;//头指针,指向头结点
public:
LinkedList();//无参的构造函数,设置头结点,也留给空链表,;
void FrontConstruct(T a[], int n);//用长度为n的T类型数组头插法初始化
void RearConstruct(T a[], int n);//用长度为n的T类型数组尾插法初始化
Node <T>* GetAddress(int i);//获得位置为i的节点地址(这个在其他函数里会被用到较多次数)
void Insert(T x, int i);//在位置为i的地方插入类型为T的x
int Locate(T x);//查找表中值为x的元素并返回其位置
T Delete(int i);//删除位置为i的节点并返回其数据
int GetLength();//获取链表长度
void PrintList();//遍历,打印
~LinkedList();//析构函数
};
template<class T>
LinkedList<T>::LinkedList() {
//设置头结点
front = new Node <T>;
front->next = NULL;
}
template<class T>
void LinkedList <T>::FrontConstruct(T a[], int n) {
if (n <= 0) throw "无法使用长度为0的数组头插法初始化";//查了,长度小于等于0好像压根就不存在?。。。
else {//普通情况,头插法
for (int i = 0; i < n; i++)
{
Node <T>* p = new Node <T>;
p->data = a[i];
p->next = front->next;
front->next = p;
}
}
}
template<class T>
void LinkedList <T>::RearConstruct(T a[], int n) {
if (n <= 0) throw "无法使用长度为0的数组尾插法初始化";//查了,长度小于等于0好像压根就不存在?。。。
else {//普通情况,尾插法
//尾插法注意要设置尾指针
Node <T>* rear = front;
for (int i = 0; i < n; i++)
{
Node <T>* p = new Node <T>;
p->data = a[i];
rear->next = p;
rear = p;
}
}
}
template <class T>
int LinkedList <T>::GetLength() {
int length = 0;
Node <T>* p = front;
while (p->next)
{
p = p->next;
length++;
//注意,对于空链表而言,p->next=NULL,循环不会执行,长度length始终为0
//而对于正常链表,length从0开始,恰好对应最后一个node的next为NULL
}
return length;
}
template <class T>
Node <T>* LinkedList <T>::GetAddress(int i) {
//获取位置为i的结点地址
if (i<1 || i>GetLength())
{
throw "您所选取的位置非法";
}
else {
int counter = 1;//空链表的情况包含在上面的if里了(length<1),所以计数器直接从1开始
Node <T>* p = front->next;//front对counter无贡献,直接跳过
while (p && counter!=i)
{
p = p->next;
counter++;
}
return p;
}
}
template <class T>
void LinkedList <T>::Insert(T x, int i) {
//插入,先想特殊情况,假如他往0位置插入那不行
if (i<1)
{
throw "插入位置非法";
}
else {
//接下来是找前一个node的位置,就分情况了,头结点和普通节点
Node <T>* p = NULL;
if (i - 1 == 0) p = front;
else p = GetAddress(i - 1);
Node <T>* s = new Node <T>;
s->data = x;
s->next = p->next;
p->next = s;
}
}
template <class T>
int LinkedList <T>::Locate(T x) {
//查找值为x的节点并返回节点位置
int counter = 1;
//空链表,其实和遍历之后找不到该值,这俩是同样的意思,相当于过早就到了表末。
Node <T>* p = front->next;//你front又没有存数据
while (p && p->data != x)//让p作为循环的一部分条件,就可以将空链表与找不到归为一类
{
p = p->next;
counter++;
}
//情况1:没找到
if (counter > GetLength())
{
cout << "未找到" << endl;
return -1;//错误没找到
}
else {
return counter;
}
}
template <class T>
T LinkedList <T>::Delete(int i) {
if (i<1 || i>GetLength())
throw "删除位置非法";
else {
//空链表没啥可删的
T a;
Node <T>* p = front;
if (i - 1 == 0) {
Node <T>* s = front->next;
a = s->data;
front->next = s->next;
delete s;
return a;
}
else {
p = GetAddress(i-1);
Node <T>* s = p->next;
a = s->data;
p->next = s->next;
//别忘了释放空间
delete s;
return a;
}
}
}
template <class T>
void LinkedList <T>::PrintList() {
if (GetLength() == 0)
cout << "此链表为空链表";
else {
Node <T>* p = front->next;
int counter = 1;
while (p)
{
cout << "这是第" << counter++ << "个节点,其数据为" << p->data << endl;
p = p->next;
}
}
}
template <class T>
LinkedList <T>::~LinkedList() {
Node <T>* p = front;
while (p)
{
front = p;
p = p->next;
delete front;
}
}
int main() {
LinkedList <int> tlist;
int arr[5] = { 2,8,2,9,31 };
tlist.FrontConstruct(arr, 5);
tlist.PrintList();
}