#pragma once
#include<assert.h>
typedef int DataType;

class SListNode
{
friend class SList; //友元:Slist能访问SListNode
public:
SListNode( DataType x )
:_data( x)
, _next( NULL)
{}

private:
DataType _data;
SListNode* _next;//SListNode*
};


class SList
{
public:
SList()
:_head( NULL)
, _tail( NULL)
{}

~SList()
{
Clear();
}

SList( const SList & s)
:_head( NULL)
, _tail( NULL)
{
SListNode* cur = s ._head; //s._head
while (cur)
{
this->PushBack(cur->_data);
cur = cur->_next;
}
}

// old method
//SList& operator=(const SList& s)
//{
// if (this != &s) //自己不能给自己赋值
// {
// this->Clear(); //??????????
// SListNode* cur = s._head; //和上面差不多
// while (cur)
// {
// this->PushBack(cur->_data);
// cur = cur->_next;
// }
// }
// return *this;
//}

//modern method
SList& operator=(SList s) //无const & (SList s)
{
swap(_head, s._head);
swap(_tail, s._tail);
return *this ;
}

public:
void PushBack(DataType x)
{
//1.空
if (_head == NULL )
{
//new一个节点,利用SListNode构造函数进行初始化
_head = new SListNode (x);
_tail = _head; //只有一个节点,_tail和_head都指向他
}
else
{
//tail->next 进行插入,再把tail移动
_tail->_next = new SListNode (x);
_tail = _tail->_next;
_tail->_next = NULL; // 不知道用不用多此一举
}
}

void PopBack()
{
//1.NULL 2.one pop 3.more ->pop
if (NULL == _head)
return;
else if (_head==_tail)
{
delete _head;
_head = NULL;
_tail = NULL;
}
else
{
SListNode* tail = _head;
SListNode* prev = NULL ;
while (tail->_next)
{
prev = tail;
tail = tail->_next;
}
delete tail;
prev->_next = NULL;
}
}
void PushFront(DataType x)
{
//1.judge 2.none 3.one 4.more
if (_head == NULL )
{
PushBack( x);
}
else if (_head == _tail)
{
_head = new SListNode (x);
_head->_next = _tail;
}
else
{
SListNode* tmp = new SListNode( x);
tmp->_next = _head;
_head = tmp;
}
}
void PopFront()
{
//judge 1.NULL 2.one 3.more
if (_head == _tail)
{
if (_head)
{
delete _head;
_head = NULL;
_tail = NULL;
}
}
else
{
SListNode* del = _head;
_head = _head->_next;
delete del;
}
}
void Insert(SListNode * pos, DataType x )
{
//judge position 1.head .tail 3.mid
assert(pos);
if (pos == _tail)
{
PushBack( x);
}
else
{
SListNode* tmp = new SListNode( x);
tmp->_next = pos->_next;
pos->_next = tmp;
}
}
SListNode* Find(DataType x)// SlistNode*
{
SListNode* cur = _head;
while(cur)
{
if (cur->_data== x )
{
return cur;
}
cur = cur->_next;
}
return NULL ;
}

void Erase(SListNode * pos)
{
//judge 1._head 2.tail 3.mid
if (pos == _head)
{
PopFront();
}
else if (pos == _tail)
{
PopBack();
}
else
{
//找前驱结点
SListNode* prev = _head;
while(prev)
{
if (prev->_next == pos )//如果前驱结点的后继等于Pos
{
//prev->next=pos->next
prev->_next = pos->_next;
delete pos ;
break;
}
//prev动起来
prev = prev->_next;
}

}
}




void Clear()
{
SListNode* cur = _head;
while (cur)
{
SListNode* del = cur;
cur = cur->_next ; //_next为私有数据 应设置友元
delete del;
}
_head = NULL;
_tail = NULL;
}


void PrintSList()
{
SListNode* cur = _head;
while (cur)
{
cout << cur->_data << "->" ;
cur = cur->_next;
}
cout << "NULL" << endl;
}
private:
SListNode* _head;//不带头结点
//SListNode head;//带头结点
SListNode* _tail;
};



void TestSList1()
{
SList s1;
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s1.PrintSList();
s1.PopBack();
s1.PopBack();
s1.PrintSList();
//SList s2(s1); //s1,s2都指向 链表1->2->3 两次析勾会造成崩溃
//s2.PrintSList();
/*SList s3;
s3 = s1;
s3.PrintSList();*/
}


//test PushFront/PopFront
void TestSList2()
{
SList s1;
s1.PushFront(1);
s1.PushFront(2);
s1.PushFront(3);
s1.PushFront(4);
s1.PushFront(5);
s1.PushFront(6);
s1.PushFront(7);
s1.PrintSList();
s1.PopFront();
s1.PopFront();
s1.PopFront();
s1.PopFront();
s1.PopFront();
s1.PrintSList();
}

//test Find/Insert
void TestSList3()
{
SList s1;
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s1.PrintSList();

SListNode* pos = s1.Find(2);
s1.Insert(pos, 10);
s1.PrintSList();
}
// Erase
void TestSList4()
{
SList s1;
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s1.PrintSList();
SListNode* pos = s1.Find(2);
s1.Erase(pos);

s1.PrintSList();
}