更新内容:
- v1.4.2 更新:添加对尾指针的支持以便PushBack()
- v1.4.3 更新:添加对前向指针的支持,使之成为双链表以便PopBack()
- v1.4.4 更新:紧急修复了空表PushFront()和PopFront()时,使用了空指针的(并不存在的)前向指针成员的bug,但代价是各添加了一个if块,会导致性能损失
- v1.4.5 更新:添加对循环链表的支持使之成为循环双链表。
老目标:
- 单链表基本实现
- 单链表的构造函数
- 完成Lab2_3
- 尾指针
- 双链表
- 循环链表
- 循环双链表
- C++多文件
- 越界异常处理
展望:
实现循环双链表后,链表的学习就告一段落了,v1.4.6更新将以bug修复为主。同时,将添加新的目标如下:
- 用 v1.4.5 或 v1.4.6 完成约瑟夫环问题的解决;
- 学习真正的C++ STL Linked List;
- 快速找到未知长度单链表的中间节点
- 链表的冒泡排序
- 欢迎指教orz
代码:
如提示未定义nullptr,请将编译器设置为C++11或取消第5行语句的注释。
//myLinkedList(TailInsert) v1.4.5
// #define TT template <typename T>
// #define mll myLinkedList
#define N 5
//#define nullptr NULL
#include <iostream>
using namespace std;
template <typename T>
struct Node
{
T data;
Node<T>* next;
Node<T>* prev;
};
template <typename T>
class myLinkedList
{
public:
myLinkedList();
myLinkedList(T a[],int n);
myLinkedList(const myLinkedList<T> & imyLinkedList);
~myLinkedList();
int Length();
bool isEmpty();
void PrintList();
T Get(int pos);
int Locate(T x);
void Insert(int i,T x);
T Delete(int i);
void InsertX(int i,T x);
T DeleteX(int i);
T PopFront();
void PushFront(T x);
void Reverse();
void Clear();
void PushBack(T x);
T PopBack();
int Test();
private:
Node<T>* first;
Node<T>* tail;
int length;
Node<T>* GetX(int pos);
};
template <typename T>
myLinkedList<T>::myLinkedList()
{
first=new Node<T>;
tail=first;
first->next=tail;
first->prev=tail;
length=0;
}
template <typename T>
myLinkedList<T>::myLinkedList(T a[],int n)
{
first=new Node<T>;
first->next=nullptr;
first->prev=nullptr;
length=0;
Node<T>* p=first;
for (int i=0;i<n;i++)
{
Node<T>* s=new Node<T>;
p->next=s;
s->prev=p;
s->next=nullptr;
s->data=a[i];
p=p->next;
length++;
}
tail=p;
tail->next=first;
first->prev=tail;
}
template <typename T>
myLinkedList<T>::myLinkedList(const myLinkedList<T> & imyLinkedList)
{
first=new Node<T>;
first->next=nullptr;
length=imyLinkedList.length;
Node<T>* p=first;
Node<T>* ip=imyLinkedList.first->next;
for (int i=0;i<length;i++)
{
Node<T>* s=new Node<T>;
s->data=ip->data;
s->next=nullptr;
s->prev=p;
p->next=s;
p=p->next;
ip=ip->next;
}
tail=p;
tail->next=first;
first->prev=tail;
}
template <typename T>
myLinkedList<T>::~myLinkedList()
{
// while(first->next!=nullptr)
while(first->next!=first)
{
Node<T>* q=first->next;
first->next=q->next;
delete q;
}
delete first;
// delete tail;
}
template <typename T>
int myLinkedList<T>::Length()
{
return length;
}
template <typename T>
bool myLinkedList<T>::isEmpty()
{
if (length==0)
return true;
else
return false;
}
template <typename T>
void myLinkedList<T>::PrintList()
{
Node<T>* p=first->next;
// while (p!=nullptr)
while (p!=first)
{
cout<<p->data<<' ';
p=p->next;
}
cout<<endl;
}
template <typename T>
T myLinkedList<T>::Get(int pos)
{
if ((pos>=1)&&(pos<=length))
{
Node<T>* p=first->next;
int cnt=1;//absPOS
//int cnt=0;//binPOS
// while (p!=nullptr)
while (p!=first)
{
if (cnt==pos)
{
break;
}
else
{
p=p->next;
cnt++;
}
}
return p->data;
}
else
{
return -1;
}
}
template <typename T>
int myLinkedList<T>::Locate(T x)
{
Node<T>* p=first->next;
int pos=1;//absPOS
// while (p!=nullptr)
while (p!=first)
{
if (x==p->data)
{
return pos;
}
else
{
pos++;
p=p->next;
}
}
return -1;
}
template <typename T>
void myLinkedList<T>::Insert(int i,T x)//insert after absPOS(i)
{
Node<T>* p=first->next;
int pos=1;
// while (p!=nullptr)
while (p!=first)
{
if (pos==i)
{
Node<T>* s=new Node<T>;
s->data=x;
s->next=p->next;
s->prev=p;
p->next=s;
s->next->prev=s;
length++;
// if (s->next==nullptr)
// tail=s;
if (s->next==first)
{
tail=s;
first->prev=tail;
}
break;
}
else
{
pos++;
p=p->next;
}
}
}
template <typename T>
T myLinkedList<T>::Delete(int i)//delete after absPOS(i)
{
Node<T>* p=first->next;
int pos=1;
// while (p!=nullptr)
while (p!=first)
{
if (pos==i)
{
Node<T>* s=p->next;
p->next=s->next;
s->next->prev=p;
// if (p->next==nullptr)
// tail=p;
if (p->next==first)
{
tail=p;
first->prev=tail;
}
T temp=s->data;
delete s;
length--;
return temp;
}
else
{
pos++;
p=p->next;
}
}
}
template <typename T>
Node<T>* myLinkedList<T>::GetX(int pos)//get absPOS
{
if ((pos>=1)&&(pos<=length))
{
Node<T>* p=first->next;
int cnt=1;//absPOS
//int cnt=0;//binPOS
// while (p!=nullptr)
while (p!=first)
{
if (cnt==pos)
{
return p;
}
else
{
p=p->next;
cnt++;
}
}
}
else
{
return nullptr;
}
}
template <typename T>
void myLinkedList<T>::InsertX(int i,T x)//insert after absPOS(i)
{
Node<T>* p=GetX(i);
Node<T>* s=new Node<T>;
s->data=x;
s->next=p->next;
p->next=s;
s->prev=p;
length++;
if (s->next==nullptr)
{
tail=s;
first->prev=tail;
}
}
template <typename T>
T myLinkedList<T>::DeleteX(int i)//delete after absPOS(i)
{
Node<T>* p=GetX(i);
Node<T>* s=p->next;
p->next=s->next;
s->next->prev=p;
// if (p->next==nullptr)
// tail=p;
if (p->next==first)
{
tail=p;
first->prev=tail;
}
T temp=s->data;
delete s;
length--;
return temp;
}
template <typename T>
T myLinkedList<T>::PopFront()
{
Node<T>* s=first->next;
T temp=s->data;
first->next=s->next;
// if (first->next==nullptr)
// tail=first;
if (first->next==first)
{
tail=first;
first->prev=tail;
}
else
s->next->prev=first;//ERROR
delete s;
length--;
return temp;
}
template <typename T>
void myLinkedList<T>::PushFront(T x)
{
Node<T>* s=new Node<T>;
s->data=x;
s->next=first->next;
if (first->next!=nullptr)
s->next->prev=s;//ERROR
// if (s->next==nullptr)
// tail=s;
if (s->next==first)
{
tail=s;
first->prev=tail;
}
first->next=s;
length++;
}
template <typename T>
void myLinkedList<T>::Reverse()
{
myLinkedList<T> temp(*this);
Clear();
while (!temp.isEmpty())
{
PushFront(temp.PopFront());
}
}
template <typename T>
void myLinkedList<T>::Clear()
{
while (!isEmpty())
{
PopFront();
}
tail=first;
tail->next=first;
first->prev=tail;
}
template <typename T>
void myLinkedList<T>::PushBack(T x)
{
Node<T>* s=new Node<T>;
s->data=x;
s->next=tail->next;
s->prev=tail;
tail->next=s;
tail=s;
length++;
first->prev=tail;
}
template <typename T>
T myLinkedList<T>::PopBack()
{
Node<T>* p=tail->prev;
Node<T>* s=tail;
T temp=s->data;
p->next=s->next;
//s->prev=nullptr;//No need to
tail=p;
delete s;
length--;
first->prev=tail;
return temp;
}
template <typename T>
int myLinkedList<T>::Test()
{
first->data=114514;
int hahaha=first->data;
return hahaha;
}
int main()
{
int arr[N]={1,2,3,4,5};
myLinkedList<int> qwe(arr,N);
qwe.InsertX(4,0);
qwe.PrintList();
qwe.DeleteX(4);
qwe.DeleteX(4);
qwe.PrintList();
//cout<<qwe.tail->prev->data;
//研究的时候以为要额外考虑到tail->prev的问题,但事实上并不“太”需要。
//cout<<"<Done.";
return 0;
}