本篇文章教你如何实现单链表操作。
目录
结构体定义
typedef int SListData;
typedef struct SListNode
{
SListData val;
struct SListNode* next;
}SListNode;
节点创建
首先分配空间,然后检查节点是否创建成功,最后进行赋值。
//创建节点
SListNode* CreateNode(SListData x)
{
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
if (newnode == NULL)//检查是否为空
{
perror("malloc:");
exit(-1);
}
newnode->next = NULL;
newnode->val = x;
return newnode;
}
尾插
尾插操作两种情况:链表为空,直接覆盖头节点,链表不为空,先找尾,再插入。
因为可能要改变头节点地址,所以传二级指针!
void PushBack(SListNode** head, SListData x)
{
assert(head);
SListNode* newnode = CreateNode(x);
if (*head == NULL)//链表为空
{
*head = newnode;
}
else
{
SListNode* tail = *head;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
头插
头插分两种情况:链表为空,链表不为空。
//头插
void PushFront(SListNode** head, SListData x)
{
assert(head);
SListNode* newnode = CreateNode(x);
if (*head == NULL)//链表为空
{
*head = newnode;
}
else
{
newnode->next = *head;
*head = newnode;
}
}
尾删
尾删分三种情况:1.链表为空,不能进行删除。 2.只有一个元素,相当于头删 3.多个元素,
要找到尾,并保留尾前一个位置。
//尾删
void PopBack(SListNode** head)
{
assert(head);
assert(*head);//链表为空
if ((*head)->next== NULL)//1个节点
{
free(*head);
*head = NULL;
}
else
{//多个节点
SListNode* cur = *head;
while (cur->next->next != NULL)
{
cur = cur->next;
}
free(cur->next);
cur->next = NULL;
}
}
头删
头删要检查链表是否为空。
void PopFront(SListNode** head)
{
assert(head);
assert(*head);
SListNode* next = (*head)->next;
free(*head);
*head = next;
}
查找
找到返回节点地址,未找到返回空。
SListNode* Find(SListNode* head, SListData x)
{
assert(head);
while (head != NULL)
{
if (head->val == x)
{
return head;
}
head = head->next;
}
return NULL;//没找到返回空
}
pos位置前插入
插入操作要确保此位置存在!
//在pos位置之前插入
void Insert(SListNode** head, SListNode* pos, SListData x)
{
assert(head);
assert(pos);检查pos
if (*head == pos)
{
PushFront(head, x);
}
else
{
SListNode* newnode = CreateNode(x);
SListNode* cur = *head;
while (cur&&cur->next!= pos)//检查pos是否在链表中
{
cur = cur->next;
}
if (cur == NULL)
{
printf("没有当前位置,无法插入");
exit(-1);
}
cur->next = newnode;
newnode->next = pos;
}
}
pos位置后插入
检查pos位置是否在链表中!
//在pos位置后插入
void InsertAfter(SListNode** head, SListNode* pos, SListData x)
{
assert(head);
assert(pos);//检查pos
SListNode* newnode = CreateNode(x);
SListNode* cur = *head;
while (cur && cur->next != pos)
{
cur = cur->next;
}
if (cur == NULL)
{
printf("链表无当前位置,无法插入");
exit(-1);
}
newnode->next = pos->next;
pos->next = newnode;
}
删除pos位置
检查pos!
//删除pos位置
void Erase(SListNode** head,SListNode*pos)
{
assert(head);
assert(pos);
if (*head == pos)
{
PopFront(head);
}
else
{
SListNode* cur = *head;
while (cur && cur->next != pos)
{
cur = cur->next;
}
if (cur == NULL)
{
printf("链表无当前位置,无法插入");
exit(-1);
}
cur->next = pos->next;
free(pos);
pos = NULL;//位置删除后,指向改位置的指针置空
}
}
销毁链表
//销毁链表
void Destory(SListNode** head)
{
assert(head);
SListNode* cur = *head;
SListNode* next = NULL;
while (cur != NULL)
{
next = cur->next;
free(cur);
cur = next;
}
*head = NULL;//注意头节点要置空
}
打印链表
void Print(SListNode* head)
{
assert(head);
while (head != NULL)
{
printf("%d ", head->val);
head = head->next;
}
}