前言
提示:文本为数据解构(三)单链表:
本文具体讲解单链表的具体使用方法
提示:以下是本篇文
系列文章目录
第一章 数据解构(一)
第二章 顺序表的具体使用方法.数据解构(二)
文章目录
前言
系列文章目录
文章目录
一、单链表视图
二、单链表使用方式
1.定义一个结构体
2.初始化
3.扩容
4.尾插
5.尾减
方法一(笨方法):
方法二:
三.总结
6.头加
7.头减
8.打印
提示:以下是本篇文章正文内容,下面案例可供参考
回顾上文说到
顺序表的使用方法
由于顺序表的缺点:
- 空间不够,需要扩容,扩容后有的扩容空间用不到,浪费空间.
- 插入数据或移动数据,删除数据都会有消耗.
所有有了单链表
单链表的优势:
- 按需来扩容,不多不少刚刚好,不用就释放,合理使用空间.
- 从头插入数据不需要挪动数据,美滋滋(不浪费空间).
单链表的缺点:
- 每一个数据都需要用指针去访问每一个节点.
- 不支持“点名访问”就像数组访问一样访问下标.
一、单链表视图
图片如下(示例):
二、单链表使用方式
1.定义一个结构体
代码如下(示例):
#include <stdio.h>
#include <stdlib.h>
typedef int SLDataType;//SLDataType
typedef struct Link_List
{
SLDataType data;//存储值
struct List* next;//存储下一个地址
}List;
SLDataType data;//存储值
struct List* next;//存储下一个地址
2.初始化
代码如下(示例):
List* str=NULL;
为一个空,主要目的为在极端可能的情况,如:头插,尾插时没有节点.
3.扩容
增容的目的是为了在输入数据时有可用空间,不多不少刚刚好
代码如下(示例):
//增容
List* SListAdd(SLDataType x)
{
List* newlist = (List*)malloc(sizeof(List));
if (newlist == NULL)
{
//增容失败直接返回
return;
}
newlist->data = x;
newlist->next = NULL;
return newlist;
}
4.尾插
代码如下(示例):
//尾插
void SListPushBack(List** pplist, SLDataType x)
{
//增加可以模块化
/*List* newlist = (List*)malloc(sizeof(List));
newlist->data = x;
newlist->next = NULL;*/
List* newlist = SListAdd(x);//创建一个新的节点
if (*pplist==NULL)//判断是否有节点
{
//没有就把newlist给pplist
*pplist = newlist;
}
else
{
//有,就找尾(null)
List* tali = *pplist;//把pplist的地址给tali
while (tali->next!=NULL)
{
tali = tali->next;
}
//把newlist的地址给尾巴
tali->next = newlist;
}
}
5.尾减
代码如下(示例):
方法一(笨方法):
//尾删
void SLPopback(List** pplist)
{
if (*pplist == NULL)
{
return;
}
//判断是否只有一个节点
if ((*pplist)->next==NULL)
{
//如果是直接释放
free(*pplist);
*pplist = NULL;
}
else
{
List* Front = *pplist;//保存倒数第2个的
List* hate = *pplist;//不断增加的
while (hate->next !=NULL)
{
hate = hate->next;
if (hate->next == NULL)
{
Front->next = NULL;
break;
}
if (hate->next != NULL)
{
Front = hate;
}
}
free(hate);
hate = NULL;
}
}
方法二:
//尾删
void SLPopback(List** pplist)
{
if (*pplist == NULL)
{
return;
}
if ((*pplist)->next==NULL)
{
free(*pplist);
*pplist = NULL;
}
else
{
List* Prev = *pplist;//保存倒数第2个的
List* tail = *pplist;//不断增加的
while (tail->next !=NULL)
{
Prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
Prev->next = NULL;
}
}
三.总结
其实方放逻辑是一样的:
如图:
6.头加
思路:(修改一下是2的值的地址给1)
代码如下(示例):
//头插
void SLPoshFront(List** pplist, SLDataType x)
{
List* newList = SListAdd(x);
newList->next = *pplist;
*pplist = newList;
}
7.头减
代码如下(示例):
//头删
void SLPopFront(List** pplist)
{
if (*pplist==NULL)
{
return;
}
else
{
List* newlist=*pplist;
free(*pplist);
*pplist = newlist->next;
}
}
8.打印
代码如下(示例):
//打印
void SLPrintf(List* plist)
{
List* LSfirst = plist;
while (LSfirst!=NULL)//判断是否有下一个节点
{
printf("%d", LSfirst->data);//打印当前节点的值
LSfirst = LSfirst->next;//寻找下一个节点
}
printf("\n");
}
while (LSfirst!=NULL)//判断是否有下一个节点
{
printf("%d", LSfirst->data);//打印当前节点的值
LSfirst = LSfirst->next;//寻找下一个节点
}