单链表
此文章看完理解透彻可能需要点时间,但是我相信你可以,记得收藏关注呦~
定义
每一个存储数据的结点,只能记录直接后继结点的位置。
一、带头结点的单链表
1、定义
有一个头结点,头结点的数据与不存储有效数据,只是使用其指针域指向第一个存储数据的结点。
2、图示:
3、实现
(1)结构体的声明
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node* next;
}LinkList;
(2)方法实现
void InitLinkList(LinkList*);//初始化
void InsertLinkList(LinkList*, ElemType, int);//插入
void InsertLinkListHead(LinkList*, ElemType);//头插
void InsertLinkListTail(LinkList*, ElemType);//尾插
void DeleteLinkList(LinkList*, int);//按位置删除
void DeleteLinkListHead(LinkList*);//头删
void DeleteLinkListTail(LinkList*);//尾删
void DeleteLinkListValue(LinkList* , ElemType);//按值删除
void ShowLinkList(LinkList *);//显示方法
void ClearLinkList(LinkList*);//清空数据
void DestroyLinkList(LinkList*);//销毁
(3)代码实现
//初始化
void InitLinkList(LinkList* list)
{
if (list == NULL) exit(0);
list->next = NULL;
}
//插入
void InsertLinkList(LinkList *list, ElemType val, int pos)
{
if (list == NULL) exit(0);
if (pos < 0)
{
printf("pos is error\n");
return;
}
LinkList* p = list;
//1、找到pos位置前的一个节点 2、如果pos超过length,则p肯定为NULL
while (pos < 0 && p != NULL)
{
p = p->next;
pos--;
}
if (p == NULL)
{
printf("pos is error\n");
return;
}
LinkList* newNode = ApplyNode(val, p->next);
if (newNode == NULL) return;
p->next = newNode;
}
//静态方法
static LinkList* ApplyNode(ElemType val, LinkList* next)
{
LinkList* s = (LinkList*)malloc(sizeof(LinkList));
if (s == NULL) return NULL;
s->data = val;
s->next = next;
return s;
}
//头插
void InsertLinkListHead(LinkList *list, ElemType val)
{
if (list == NULL) exit(0);
InsertLinkList(list, val, 0);
}
//尾插
void InsertLinkListTail(LinkList* list, ElemType val)
{
if (list == NULL) exit(0);
LinkList* p = list;
while (p->next != NULL) p = p->next;
LinkList* s = ApplyNode(val, NULL);
if (s == NULL) return;
p->next = s;
}
//按位置删除
void DeleteLinkList(LinkList *list, int pos)
{
if (list == NULL) exit(0);
LinkList* p = list;
while (pos && p->next != NULL)
{
p = p->next;
pos--;
}
if (p->next == NULL) return;
LinkList* q = p->next;
p->next = q->next;
free(q);
}
//头删
void DeleteLinkListHead(LinkList *list)
{
if (list == NULL) exit(0);
DeleteLinkList(list, 0);
}
//尾删
void DeleteLinkListTail(LinkList* list)
{
if (list == NULL) exit(0);
LinkList* p = list;
LinkList* q = p->next;
while (q != NULL && q->next != NULL)
{
p = p->next;
q = q->next;
}
if (q == NULL) return;
p->next = NULL;
free(q);
}
//按值删除
void DeleteLinkListValue(LinkList *list, ElemType val)
{
if (list == NULL) exit(0);
LinkList* p = list;
LinkList* q = p->next;
while (q != NULL)
{
if (q->data == val)
{
p->next = q->next;
free(q);
q = p->next;
}
else
{
p = q;
q = q->next;
}
}
}
//显示方法
void ShowLinkList(LinkList* list)
{
if (list == NULL) exit(0);
LinkList* p = list->next;
while (p != NULL)
{
printf("%d-->", p->data);
p = p->next;
}
printf("\n");
}
//清空数据
void ClearLinkList(LinkList* list)
{
if (list == NULL) exit(0);
while (list->next != NULL) DeleteLinkListHead(list);
}
//销毁数据
void DestroyLinkList(LinkList *list)
{
if (list == NULL) exit(0);
ClearLinkList(list);
}
二、头指针单链表
1、定义
只有一个结点指针,只用这个结点指针保存第一个数据结点的地址
2、图示
和带头点的单链表实现的区别:插入时为空链的特殊处理和删除第一个结点的特殊处理。
3、实现
(1)结构体声明
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node* next;
}List;
(2)方法实现
void InitList(List **list);//初始化
void InsertList(List** list, ElemType val, int pos);//插入
void InsertListHead(List** list, ElemType val);//头插
void InsertListTail(List** list, ElemType val);//尾插
void DeleteList(List** list, int pos);//按位置删除
void DeleteListHead(List** list);//头删
void DeleteListTail(List** list);//尾删
void DeleteListValue(List** list, ElemType val);//按值删除
void ShowList(List** list);//显示方法
void DestroyList(List** list);//销毁
(3)代码实现
//初始化
void InitList(List **list)
{
if (list == NULL) exit(0);
*list = NULL;
}
//按位置插入
void InsertList(List** list, ElemType val, int pos)
{
if (list == NULL) exit(0);
if (pos < 0)
{
printf("Insert::pos is error\n");
return;
}
if (pos == 0)
{
InsertListHead(list, val);
}
else
{
List* p = *list;
while (pos > 1 && p != NULL)
{
p = p->next;
pos--;
}
if (p == NULL)
{
printf("Insert::pos is error\n");
}
else
{
List* newNode = _ApplyNode(val, p->next);
if (newNode == NULL) exit(0);
p->next = newNode;
}
}
}
//静态方法申请新结点
static List* _ApplyNode(ElemType val, List* next)
{
List* s = (List*)malloc(sizeof(List));
if (s == NULL) return NULL;
s->data = val;
s->next = next;
return s;
}
//头插
void InsertListHead(List** list, ElemType val)
{
if (list == NULL) exit(0);
List* newNode = _ApplyNode(val, *list);
if (newNode == NULL) exit(0);
*list = newNode;
}
//尾插
void InsertListTail(List** list, ElemType val)
{
if (list == NULL) exit(0);
if (*list == NULL)
{
InsertListHead(list, val);
return;
}
List* p = *list;
while (p->next != NULL)
{
p = p->next;
}
p->next = _ApplyNode(val, NULL);
}
//按位置删除
void DeleteList(List** list, int pos)
{
if (list == NULL) exit(0);
if (*list == NULL)
{
printf("List is Empty\n");
return;
}
if (pos < 0)
{
printf("Delete::pos is error\n");
}
if (pos == 0)
{
DeleteListHead(list);
}
else
{
List* p = *list;
while (pos > 1 && p->next != NULL)
{
p = p->next;
pos--;
}
if (p->next == NULL)
{
printf("Delete::pos is error\n");
}
else
{
List* q = p->next;
p->next = q->next;
free(q);
}
}
}
//头删
void DeleteListHead(List** list)
{
if (list == NULL) exit(0);
if (*list == NULL)
{
printf("List is Empty\n");
return;
}
List* p = *list;
*list = p->next;
free(p);
}
//尾删
void DeleteListTail(List** list)
{
if (list == NULL) exit(0);
if (*list == NULL)
{
printf("List is Empty\n");
return;
}
//仅剩下一个节点时,调用头删
if ((*list)->next == NULL)
{
DeleteListHead(list);
return;
}
List *p = *list;
List *q = p->next;
while (q->next != NULL)
{
p = q;
q = q->next;
}
p->next = NULL;
free(q);
}
//按值删除
void DeleteListValue(List** list, ElemType val)
{
if (list == NULL) exit(0);
if (*list == NULL) return;
if((*list)->data == val)
{
DeleteListHead(list);
DeleteListValue(list, val);
}
else
{
List* p = *list;
List* q = p->next;
while (q != NULL)
{
if (q->data == val)
{
p->next = q->next;
free(q);
q = p->next;
}
else
{
p = q;
q = q->next;
}
}
}
}
//显示方法
void ShowList(List** list)
{
if (list == NULL) exit(0);
List* p = *list;
while (p != NULL)
{
printf("%d-->", p->data);
p = p->next;
}
printf("NULL\n");
}
//销毁
void DestroyList(List** list)
{
if (list == NULL) exit(0);
while (*list != NULL)
{
DeleteListHead(list);
}
}
总结:
1、链表存储数据时,在逻辑上时连续的,但是在物理空间上不连续。既然在物理空间上不连续,那么就不能使用下标来访问链表中的结点。
2、链表的查找需要遍历,且必须从头遍历。
在平时编写代码的时候,我们应该要注意编程的规范,才回保证我们的系统稳定运行。一本《高质量C/C++编程指南》介绍给大家。
此文章仅代表自己(本菜鸟)学习积累记录,或者学习笔记,如有侵权,请联系作者删除。人无完人,文章也一样,文笔稚嫩,在下不才,勿喷,如果有错误之处,还望指出,感激不尽~
技术之路不在一时,山高水长,纵使缓慢,驰而不息。