文章目录
1. 创建结构体
typedef struct LNode
{
/*
单链表
LNode 表示单个结点
*/
ElemType data;
struct LNode *next;
}LNode;
2. 定义增加新节点(动态申请空间)的函数createLinkListNode
LNode *creatLinkListNode(ElemType element)
{
/*
新增一个结点
*/
LNode *newNode = (LNode *)malloc(sizeof(LNode));
if (newNode == NULL)
{
printf("申请空间失败!!!\n");
}else{
newNode->data = element;
newNode->next = NULL;
}
return newNode;
}
3. 单链表的头部增加元素
void LinkListPushFront(LNode **ListHead, ElemType element)
{
/*
单链表头插元素
*/
LNode *newNode = creatLinkListNode(element); //开辟一个新的结点
newNode->next = *ListHead; //指向链表头结点
*ListHead = newNode; //将头指针指向新的头结点
}
4. 单链表头部删除元素
void LinkListPopFront(LNode **ListHead)
{
/*
单链表删除头结点
*/
//1. 空链表
if (*ListHead == NULL)
{
return;
}
//2. 只有一个结点的单链表 + 3. 有两个及以上结点的单链表
else{
LNode *tamp = (*ListHead)->next;
free(*ListHead);
*ListHead = tamp;
}
}
5. 单链表尾部增加元素
void LinkListPushBack(LNode **phead, ElemType element)
{
/*
向单链表尾插一个新结点,存储值x
*/
LNode *tail = *phead;
LNode *newNode = creatLinkListNode(element);
if (*phead == NULL)
{
//指向的单链表为空
*phead = newNode;
}else{
//指向的单链表不为空
while (tail->next != NULL)
{
//找到尾结点
tail = tail->next;
}
//newNode = creatLinkListNode(element);
//插入新结点到单链表表尾
tail->next = newNode;
}
}
6. 单链表尾部删除元素
void LinkListPopBack(LNode **phead)
{
/*
删除单链表尾部结点
*/
//1. 链表为空
if (*phead == NULL)
{
return;
}
//2. 只有一个结点
else if ((*phead)->next == NULL)
{
free(*phead);
*phead = NULL;
}
//3. 有两个及以上结点
else{
LNode *tail = *phead;
LNode *prev = NULL;
while(tail->next != NULL)
{
prev = tail; //存储前一个结点地址的指针
tail = tail->next;
}
free(tail);
tail = NULL; //此步骤可写可不写,写上好习惯。因为是临时变量,和上面的2的情况不一样。
prev->next = NULL;
}
}
7. 单链表指定位置增加元素
void LinkListInsert(LNode **List, int position, ElemType element)
{
/*
单链表指定位置插入元素
*/
//判断插入位置的合法性
if (position > GetLenghth(*List) || position < 1)
{
printf("查出链表范围,请输入合法的位置插入元素!\n");
}else{
LNode *newNode = creatLinkListNode(element);
LNode *pos = *List; //在以下"2."部分中查找位置并插入时使用此临时指针,
//不可直接用头指针,位置会发生改变,导致链表发生改变
int tamp = 0;
//1. 插入位置为头部
if (position - 1 == 0)
{
newNode->next = *List;
*List = newNode;
}
//2. 插入位置不为头部
else{
while (position - 2 != tamp)
{
//找到插入位置前一个结点
tamp++;
pos = pos->next;
}
newNode->next = pos->next;
pos->next = newNode;
}
}
}
8. 单链表指定位置删除元素
void LinkListDeleteNode(LNode **List, int position)
{
/*
删除指定位置结点及元素
*/
//1. 空链表
if ((*List) == NULL)
{
printf("此链表为空,无可删除结点。\n");
}
//2. 非空链表
else if (position > GetLenghth(*List) || position < 1)
{
//判断合法性
printf("超出范围,请输入合法位置!\n");
}
else{
//2.1 删除位置为头部
if (position - 1 == 0)
{
LNode *tamp = (*List)->next; //释放头指针指向的空间后会变成野指针,
//需要通过tamp将其拉回链表中,变回头指针。
free(*List);
*List = tamp;
}
//2.2 删除位置不为头部
else{
int i = 0;
LNode *sreachPosition = *List;
LNode *PrePosition;
while(position - 1 != i)
{
i++;
PrePosition = sreachPosition;
sreachPosition = sreachPosition->next;
}
PrePosition->next = sreachPosition->next;
free(sreachPosition);
sreachPosition->next = NULL;
}
}
}
9. 单链表查询元素
void LinkListSreach(LNode *ListHead, ElemType element)
{
/*
单链表查找元素
*/
LNode *cur = ListHead;
int num = 0;
while (cur)
{
if (cur->data == element)
{
//找到指定的元素则返回
printf("所查找的元素\"%d\"在链表的第%d位置.\n", element, num+1);
break;
}
//未找到指向下一个结点
cur = cur->next;
num++;
}
//走到此步说明所要查找的元素不存在
if (cur == NULL)
{
printf("查找元素不存在!!\n");
}
}
10. 单链表更改指定位置的元素
void LinkListChangeElement(LNode *List, int position, ElemType newElement)
{
/*
单链表改变指定位置的元素
*/
int i = 0;
int ListLenght = GetLenghth(List);
if (position > ListLenght || position < 1)
{
printf("请输入正确的位置修改元素!!\n");
}
else{
while (1)
{
if (position-1 == i)
{
List->data = newElement;
break;
}
i++;
List = List->next;
}
printf("修改元素成功!!\n");
}
}
11. 单链表返回链表长度
int GetLenghth(LNode *LinkList)
{
/*
获取链表的长度
*/
int num = 0;
while (LinkList != NULL)
{
LinkList = LinkList->next;
num++;
}
return num;
}
- 打印单链表
void LinkListPrint(LNode *phead)
{
/*
遍历并打印链表中的值
*/
LNode *cur = phead;
while (cur != NULL)
{
//一致遍历到尾指针
printf("%d -> ", cur->data);
cur = cur->next;
}
printf("null\n"); //单链表最后一个结点指向的空值
}
12. 功能测试
int main()
{
//定义单链表
LNode *Liste = NULL;
LNode *emptyLinkList = NULL;
//尾插新元素
LinkListPushBack(&Liste, 1);
LinkListPushBack(&Liste, 2);
LinkListPushBack(&Liste, 3);
//遍历单链表并打印data
LinkListPrint(Liste);
//尾部删除元素
LinkListPopBack(&Liste);
//遍历单链表并打印data
LinkListPrint(Liste);
//头插新元素
LinkListPushFront(&Liste, 725);
//遍历单链表并打印data
LinkListPrint(Liste);
//头删新元素
LinkListPopFront(&Liste);
//遍历单链表并打印data
LinkListPrint(Liste);
//查找元素
LinkListSreach(Liste, 2);
LinkListSreach(Liste, 725);
//获取链表长度
printf("链表长度为%d\n", GetLenghth(Liste));
//改变指定位置的元素
LinkListChangeElement(Liste, 2, 12);
LinkListChangeElement(Liste, 1, 711);
LinkListChangeElement(Liste, 0, 111);
LinkListChangeElement(Liste, 3, 222);
//指定位置插入元素
LinkListInsert(&Liste, 2, 33);
LinkListInsert(&Liste, 1, 22);
LinkListInsert(&Liste, 4, 91);
//遍历单链表并打印data
LinkListPrint(Liste);
//指定位置删除元素
LinkListDeleteNode(&Liste, 1);
//遍历单链表并打印data
LinkListPrint(Liste);
//指定位置删除元素
LinkListDeleteNode(&Liste, 2);
LinkListDeleteNode(&Liste, 3);
//遍历单链表并打印data
LinkListPrint(Liste);
//指定位置删除,空链表version test
LinkListDeleteNode(&emptyLinkList, 1);
return 0;
}
测试结果: