单链表是一种基础线性数据结构,其结构分为数据域和指针域两部分,数据域用于存放数据,可以是一个整型,一个数组,一个结构体等等,指针域用于存放一个指针,指向下一个链表节点,每个节点通过指针联系,其物理地址不一定连续。单链表节点的结构体如下:
typedef struct Node
{
DataType data; //数据域
struct Node *next; //指向结构体的指针
}LNode,*PNode;
单链表的初始化时可以让头节点的数据域为空,也可以在其中放入数据,这就有两种不同的单链表,基于两种单链表的操作有一定区别,头结点数据域为空时访问后继节点或者其他操作都不会改变头指针的指向,下面的操作是基于头节点数据域不为空的单链表进行的。
PNode LinkList; //建立头节点
void Init_List(PNode *PHead) //初始化 PHead为指向头节点的指针
{
assert(PHead);
*PHead = NULL; //头指针置空
}
PNode Set_Node(DataType data) //新建节点
{
PNode Node = (PNode)malloc(sizeof(LNode));
if (NULL == Node)
{
perror("out of memory");
return NULL;
}
else
{
Node->data = data;
Node->next = NULL;
}
return Node; //返回节点指针
}
void Push_Back(PNode *PHead,DataType data) //尾插,插入到链表最后
{
assert(NULL != PHead);
if (*PHead == NULL)
{
*PHead=Set_Node(data); //链表中没有节点
}
else
{
PNode TmpNode = *PHead;
while (TmpNode->next != NULL)
{
TmpNode = TmpNode->next; //找到最后一个节点
}
TmpNode->next = Set_Node(data);
}
}
void Pop_Back(PNode *PHead) //尾删
{
PNode TmpNode = NULL;
PNode PreNode = NULL;
assert(NULL != PHead);
if (NULL == *PHead)
{
return;
}
TmpNode = *PHead;
PreNode = *PHead;
while (TmpNode->next != NULL)
{
PreNode = TmpNode;
TmpNode = TmpNode->next; //查找最后一个节点
}
PreNode->next = NULL;
free(TmpNode);
}
void Push_Front(PNode* pHead, DataType data) //头插
{
assert(pHead);
if (NULL == *pHead)
{
*pHead = Set_Node(data);
}
else
{
PNode TmpNode = *pHead;
*pHead = Set_Node(data);
(*pHead)->next = TmpNode;
}
}
void Pop_Front(PNode* pHead) //头删
{
assert(pHead);
if (*pHead == NULL)
{
return;
}
else
{
PNode TmpNode = *pHead;
*pHead = (*pHead)->next;
free(TmpNode);
}
}
void Print_List(PNode Head) //遍历打印并打印
{
PNode TmpNode = NULL;
assert(NULL != Head);
TmpNode = Head;
while (TmpNode != NULL)
{
printf("%d->", TmpNode->data);
TmpNode = TmpNode->next;
}
printf("NULL");
printf("\n");
}
PNode Find(PNode pHead, DataType data) //查找数据域为data的节点位置
{
PNode TmpNode = NULL;
assert(pHead);
TmpNode = pHead;
while (TmpNode->data != data)
{
if (TmpNode->next != NULL)
{
TmpNode = TmpNode->next;
}
else
{
return NULL;
}
}
return TmpNode;
}
void Insert(PNode* pHead, PNode pos, DataType data) //任意位置(pos)插入节点
{
PNode TmpNode = NULL;
PNode PreNode = NULL;
assert(pHead);
if (*pHead == NULL)
{
return;
}
TmpNode = *pHead;
if (TmpNode == pos)
{
Push_Front(&(*pHead), data); //调用头插
return;
}
while (TmpNode->next != pos)
{
if (TmpNode->next != NULL)
{
TmpNode = TmpNode->next;
PreNode = TmpNode->next;
}
else
{
return; //pos节点不在链表中
}
}
TmpNode->next = Set_Node(data);
TmpNode->next->next= PreNode;
}
void Erase(PNode* pHead, PNode pos) //删除任意位置(pos)节点
{
PNode TmpNode = NULL;
PNode PreNode = NULL;
assert(pHead);
if (*pHead == NULL)
{
return;
}
TmpNode = *pHead;
if (*pHead == pos) //pos为头节点
{
*pHead = NULL;
free(TmpNode);
return;
}
PreNode = TmpNode->next;
while (TmpNode->next!= pos)
{
if (TmpNode->next != NULL)
{
TmpNode = TmpNode->next;
PreNode = TmpNode->next;
}
else
{
return; //pos节点不在链表中
}
}
TmpNode->next = PreNode->next;
free(PreNode);
}
void RemoveAll(PNode* pHead, DataType data) //删除数据域为data的节点
{
assert(pHead);
if (*pHead == NULL)
{
return;
}
while (Find(*pHead ,data)!=NULL)
{
Remove(&(*pHead), data);
}
}
void Remove(PNode *Phead, DataType data) //删除数据data所在节点
{
assert(Phead);
if (*Phead == NULL)
{
return;
}
Erase(&(*Phead), Find(*Phead, data)); //调用函数
}
void RemoveAll(PNode* pHead, DataType data) //删除所有数据域为data的节点
{
assert(pHead);
if (*pHead == NULL)
{
return;
}
while (Find(*pHead ,data)!=NULL)
{
Remove(&(*pHead), data); //调用函数
}
}
int Length(PNode PHead) //求表长
{
int count = 0;
PNode pCurNode = PHead;
if (PHead == NULL)
{
return 0;
}
while (pCurNode != NULL)
{
count++;
pCurNode = pCurNode->next;
}
return count;
}