链表是一种物理存储结构上非连续,非顺序的存储结构,用于存储逻辑关系为 "一对一" 的数据。数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
1.链表的特征
1.申请的空间可以不连续
2.访问元素不方便,插入,删除相对于比较方便
头结点:数据域无效
首结点:第一个数据域有效的结点
尾结点:指针域无效
空链表:既是头结点又是尾结点
2.链表的分类
有没有头结点:带头结点的链表和不带头结点的链表(一般使用的是带头结点的链表)
指针域是双向还是单项:单项链表和双向链表
尾结点是否指向头结点:循环链表和不循环链表
3.顺序表的基本操作
3.1链表的结构定义
//数据元素类型
typedef int data_type;
typedef struct linknode
{
data_type data;//数据域
struct linknode *pNext;//指针域
}Link;
3.2创建一个链表
Link *creatLink(void)
{
//定义一个指针变量用来接收malloc的返回值
Link *pLink = NULL;
//申请空间
pLink = (Link *)malloc(sizeof(Link));
//判断
if(NULL == pLink)
{
perror("malloc error!");
return NULL;
}
memset(pLink,0,sizeof(Link));
return pLink;
}
3.3插入链表
3.3.1头插法
case HEAD:
//判断头结点的指针域是否为空
if(pHead -> pNext != NULL)
{
pNew->pNext = pHead->pNext;
}
//插入新的结点
pHead->pNext = pNew;
break;
3.3.2尾插法
case TAIL:
//初始化为头结点
pTail = pHead;
//当pTail的指针域不为空的时候,循环遍历
while(pTail->pNext != NULL)
{
pTail = pTail->pNext;
}
//插入新结点
pTail->pNext = pNew;
break;
3.3.3中间插入
default:
pTail = pHead;
while(pTail !=NULL && i < pos-1)
{
pTail = pTail->pNext;
i++;
}
if(NULL == pTail)
{
printf("位置错误!\n");
return EMPTY;
}
pNew->pNext = pTail->pNext;
pTail->pNext = pNew;
3.4显示操作
int showLink(Link *pHead)
{
//入参判断
if(NULL == pHead)
{
return LINKERROR;
}
//定义一个结构体指针
Link *pTmp = NULL;
//初始化为首结点
pTmp = pHead->pNext;
//循环遍历,直到指针域为空
while(pTmp != NULL)
{
printf("%d\t",pTmp->data);
pTmp = pTmp->pNext;
}
printf("\n");
return OK;
}
3.5删除操作
3.5.1头删法
case HEAD:
//找到要删除结点
pDel = pHead->pNext;
//保存删除位置的数据
*pData = pDel->data;
//保存要删除后的所有结点
pHead->pNext = pDel->pNext;
//释放
free(pDel);
pDel = NULL;
break;
3.5.2尾删法
case TAIL:
//初始化两个指针变量,一个为头结点,一个为首结点
pPer = pHead;
pDel = pHead->pNext;
//判断是否头结点的指针域为空
if(NULL == pDel)
{
return EMPTY;
}
//循环
while(pDel->pNext != NULL)
{
//两个指针同时向后移动
pPer = pDel;
pDel = pDel->pNext;
}
//保存要删除结点的数据
*pData = pDel->data;
//置空
pPer->pNext = NULL;
//释放
free(pDel);
pDel = NULL;
break;
3.5.3中间删除
default:
//初始化一个结点为头结点,一个结点为首结点
pPer = pHead;
pDel = pHead->pNext;
//判断
//循环
while(pDel != NULL && i< pos-1)
{
pPer = pDel;
pDel = pDel->pNext;
i++;
}
//保存要删除结点的数据
if(NULL == pDel)
{
return EMPTY;
}
*pData = pDel->data;
pPer->pNext = pDel->pNext;
//释放
free(pDel);
pDel = NULL;
3.6销毁链表
int destroyLink(Link **pLink)
{
//入参判断
if(NULL == *pLink)
{
return LINKERROR;
}
while(1)
{
//按照头删法的思想,挨个删除,直到为空
Link *pDel = (*pLink)->pNext;
if(NULL == pDel)
{
break;
}
//删除一个后边的不动
(*pLink)->pNext = pDel->pNext;
//释放
free(pDel);
pDel = NULL;
}
free(*pLink);
*pLink = NULL;
return OK;
}
4程序运行结果