#pragma once

#include <stdio.h>
#include <malloc.h>
#include <assert.h>

typedef int DataType;

typedef struct Node
{
DataType data;
struct Node* next;
}Node, *PLinkList;

//struct Node*

// 初始化/销毁 /打印单链表
void InitList(PLinkList* list);
void PrintList(PLinkList list);
int GetLength(PLinkList list);

void PushBack(PLinkList* ppList, DataType x);
void PushFront(PLinkList* ppList, DataType x);


Node* Find(PLinkList pList, DataType x);
void Insert(PLinkList* ppList, Node * n, DataType x);
void Remove(PLinkList* ppList, Node * n);
void Erase(PLinkList* ppList, DataType x,DataType all);
void DelMidNode(Node*n);

void InsertFrontNode(Node *n,DataType x);
void Reverse(PLinkList* ppList);
void Sort(PLinkList pList);



PLinkList _CreateNode(DataType x)
{
PLinkList tmp = (PLinkList)malloc(sizeof(Node));
tmp->data = x;
tmp->next = NULL;

return tmp;
}

void InitList(PLinkList* ppList)
{
assert(ppList);

*ppList = 0;
}

void PrintList(PLinkList pList)
{
PLinkList begin = pList;
while (begin != NULL)
{
printf("%d->", begin->data);
begin = begin->next;
}

printf("NULL\n");
}

int GetLength(PLinkList pList)
{
int count = 0;
PLinkList begin = pList;

while (begin != NULL)
{
count++;
begin = begin->next;
}

return count;
}

void PushBack(PLinkList* ppList, DataType x)
{
assert(ppList);
PLinkList tmp = *ppList;
if (*ppList == NULL)
*ppList = _CreateNode(x);
else
{
while (tmp->next != NULL)
{
tmp = tmp->next;
}
tmp->next = _CreateNode(x);
}
}

void PushFront(PLinkList* ppList, DataType x)
{
assert(ppList);

// 1.没有节点
// 2.有多个节点
if (*ppList == NULL)
{
*ppList = _CreateNode(x);
}
else
{
PLinkList tmp = _CreateNode(x);
tmp->next = *ppList;
*ppList = tmp;
}
}

void PopFront(PLinkList* ppList)
{
PLinkList tmp;
assert(ppList);

if (*ppList == NULL)
{
printf("List Is Empty\n");
return;
}

tmp = *ppList;
*ppList = (*ppList)->next;
free(tmp);
}

void PopBack(PLinkList* ppList)
{
assert(ppList);

if (*ppList == NULL)
{
printf("List Is Empty!\n");
return;
}
else
{
PLinkList prev, end;
prev = NULL;
end = *ppList;
while (end->next != NULL)
{
prev = end;
end = end->next;
}
free(end);
if (prev == NULL)
{
*ppList = NULL;
}
else
{
prev->next = NULL;
}
}
}


Node* Find(PLinkList pList, DataType x)
{
assert(pList);
PLinkList begin=pList;
while (begin != NULL)
{
if (begin->data ==x)
{
return begin;
}
begin = begin->next;
}
return NULL;
}

void Insert(PLinkList* ppList, Node * n, DataType x)
{
assert(ppList);
PLinkList tmp;
if (*ppList == NULL)
{
*ppList = _CreateNode(x);
return;
}
tmp=_CreateNode(x);
tmp->next = n->next;
n->next=tmp;
}

void DelMidNode(Node*n)
{
assert(n);
if (n == NULL)
{
printf("n Is NULL!\n");
}
else if (n->next == NULL)
{
printf("n Is Tail!\n");
}
else
{
Node* del = n->next;
n->data = del->data;
n->next = del->next;
free(del);
del = NULL;
}
}


void Remove(PLinkList* ppList, Node * n)
{
/*assert(ppList);
if ((*ppList)->next == NULL)
PopBack(&ppList);
else
DelMidNode(n);
*/

assert(ppList);
PLinkList prev = *ppList, end = 0;
//仅仅有一个节点
if ((*ppList)->next == NULL)
{
free(*ppList);
*ppList = NULL;
return;
}
//链表有一个以上的节点
else
{
if (*ppList == n)
{
*ppList = (*ppList)->next;
free(prev);
return;
}
else
{
while (prev != NULL&&prev != n)
{
end = prev;
prev = prev->next;
}
if (prev == n)
{
end->next = n->next;
free(n);
return;
}
}
}
}
//0.删除第一个x
//非0.删除全部x
void Erase(PLinkList* ppList, DataType x,DataType all)
{
assert(ppList);
PLinkList tmp=*ppList ;
do
{
Node* ret = Find(ppList, x);
tmp = ret->next;
Remove(&ppList, ret);
} while (tmp != NULL&&all != 0);
}


void InsertFrontNode(Node *n, DataType x)
{
assert(n);
if (n == NULL)
{
printf("n Is NULL!\n");
}
else if (n->next==NULL)
{
n->next= _CreateNode(x);
PLinkList *tmp = n->data;
n ->data= n->next->data;
n->next->data = tmp;
n->next->next = NULL;
}
else
{
Insert(n, n, x);
PLinkList *tmp = n->data,end=n->next->next;
n->data = n->next->data;
n->next->data = tmp;
}
}

void Reverse(PLinkList* ppList)
{
assert(ppList);
if (*ppList != NULL)
{
Node* newhead = *ppList;
Node *begin = (*ppList)->next;
newhead->next = NULL;
while (begin != NULL)
{
Node* tmp = begin;
begin = begin->next;
tmp->next = newhead;
newhead = tmp;
}
*ppList = newhead;
}
}
void Sort(PLinkList pList)
{
assert(pList);
if (pList == NULL)
{
printf("List Is NULL!\n");
return;
}
else if (pList->next == NULL)
{
printf("There Is Only One Node In This List!\n");
return;
}
else
{
PLinkList tmp=0,end=pList;
PLinkList begin = pList;
for (; end ->next!= NULL; )
{
for (begin=pList; begin->next != NULL; begin=begin->next)
{
if ((begin->data) < (begin->next->data))
{
tmp = begin->data;
begin->data = begin->next->data;
begin->next->data = tmp;
}
}
end = end->next;
}
}
}



#include "Slist.h"

void Test1()
{
PLinkList pList;
InitList(&pList);

PushBack(&pList, 1);
PushBack(&pList, 2);
PushBack(&pList, 3);
PushBack(&pList, 4);
PrintList(pList);

GetLength(pList);
PrintList(pList);
printf("Length: %d\n", GetLength(pList));
}

void Test2()
{
PLinkList pList;
InitList(&pList);

PushFront(&pList, 1);
PushFront(&pList, 2);
PushFront(&pList, 3);
PushFront(&pList, 4);

PopFront(&pList);
PopFront(&pList);
PopFront(&pList);
PopFront(&pList);
PopFront(&pList);


GetLength(pList);
PrintList(pList);
printf("Length: %d\n", GetLength(pList));
}

void Test3()
{
PLinkList pList;
InitList(&pList);

PushFront(&pList, 1);
PushFront(&pList, 2);
PushFront(&pList, 3);
PushFront(&pList, 4);
PrintList(pList);

PopBack(&pList);
PopBack(&pList);
PopBack(&pList);
PopBack(&pList);

PrintList(pList);

GetLength(pList);
PrintList(pList);
printf("Length: %d\n", GetLength(pList));
}

void Test4()
{
PLinkList pList;
InitList(&pList);


PushFront(&pList, 1);
PushFront(&pList, 2);
PushFront(&pList, 3);
PushFront(&pList, 4);

PrintList(pList);

Node* ret = Find(pList, 1);
if (ret != NULL)
{
Insert(&pList, ret, 0);
}
PrintList(pList);

Node* ret1 = Find(pList, 0);
Remove(&pList, ret1);
PrintList(pList);
}

Test5()
{
PLinkList pList;
InitList(&pList);

PushFront(&pList, 1);
PushFront(&pList, 2);
PushFront(&pList, 3);
PushFront(&pList, 4);

PrintList(pList);

Node* ret = Find(pList, 1);
DelMidNode(ret);
PrintList(pList);
ret = Find(pList, 4);
DelMidNode(ret);
PrintList(pList);
ret = Find(pList, 2);
DelMidNode(ret);
PrintList(pList);

Node* ret1 = Find(pList, 1);
InsertFrontNode(ret1, 2);
PrintList(pList);

Node* ret2 = Find(pList, 3);
InsertFrontNode(ret2, 4);
PrintList(pList);


}

Test6()
{
PLinkList pList;
InitList(&pList);

PushFront(&pList, 1);
PushFront(&pList, 1);
PushFront(&pList, 1);
PushFront(&pList, 2);
PushFront(&pList, 3);
PushFront(&pList, 4);
PushFront(&pList, 5);
PushFront(&pList, 6);
PushFront(&pList, 7);
PrintList(pList);

Erase(pList, 1, 0);
PrintList(pList);

Erase(pList, 1, 1);
PrintList(pList);

Reverse(&pList);
PrintList(pList);

Sort(pList);
PrintList(pList);
}

int main()
{
//Test1();
//Test2();
//Test3();
//Test4();
Test5();
//Test6();
return 0;
}