链表 v1.4.5

更新内容:

  • 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;
}
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页