一,实现功能
1.实现链表的三种插入方法:头插法,尾插法,中间插入
2.实现链表的三种删除方法:头删法,尾删法,中间删除法
*同时为了验证结果实现了链表的显示
二,步骤
1.创建一个链表中的节点
//创建链表中的节点
Link *create_link(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;
}
2.根据位置插入链表里的元素
int insert_link(Link *pHead,int pos,data_type item)
{
//入参判断
if(NULL == pHead)
{
return LINKNULL;
}
//创建新节点
Link *pNew = (Link *)malloc(sizeof(Link));
if(NULL == pNew)
{
perror("malloc error");
return MALLOCERROR;
}
memset(pNew,0,sizeof(Link));
//将新值赋值给新节点的数据域
pNew->data = item;
//根据位置向链表中插入元素
Link *pTail = NULL;
Link *pPre1 = NULL;
Link *pPre2 = NULL;
int i = 0;
switch(pos)
{
//头插法
case HEAD:
//先保护好要插入节点后的所有节点
if(pHead->pNext != NULL)
{
pNew->pNext = pHead->pNext;
}
//将新节点插入进去
pHead->pNext = pNew;
break;
//尾删法
case TAIL:
//定义一个指针变量,初始化为头节点
pTail = pHead;
//当pTail->pNext不为空的时候
while(pTail->pNext != NULL)
{
pTail = pTail->pNext;
}
//将新节点插入进去
pTail->pNext = pNew;
break;
//中间插入
default:
//定义两个结构体指针变量一个指向头节点一个指向首节点
pPre1=pHead;
pPre2=pHead->pNext;
while(pPre2 != NULL && i<pos-1)
{
pPre1=pPre2;
pPre2=pPre2->pNext;
i++;
}
//当pPre2不等于空时,移动pos-1个位置
if(NULL == pPre2)
{
return EMPTY;
}
//保护要插入元素后的所有节点
pNew->pNext=pPre2;
//插入元素
pPre1->pNext=pNew;
}
return OK;
}
3.显示链表里元素的内容
int show_link(Link *pHead)
{
//入参判断
if(NULL == pHead)
{
return LINKNULL;
}
//定义一个结构体指针,初始化为首节点
Link *pTmp = NULL;
pTmp = pHead->pNext;
//循环遍历,直到pTmp->pNext为空为止
while(pTmp != NULL)
{
printf("%d\t",pTmp->data);
pTmp = pTmp->pNext;
}
printf("\n");
return OK;
}
4.根据位置删除链表的元素
int delete_link(Link *pHead,int pos,data_type *pData)
{
//入参判断
if(NULL == pHead)
{
return LINKNULL;
}
//定义一个结构体指针变量,保存要删除的节点的首地址
Link *pDel = NULL;
Link *pPre = NULL;
int i = 0;
switch(pos)
{
case HEAD:
//找到要删除的节点
pDel = pHead->pNext;
//头删法
// 保存要删除的数据
*pData = pDel->data;
// 保存要删除节点后的所有节点
pHead->pNext = pDel->pNext;
//释放pDel
free(pDel);
pDel = NULL;
break;
//尾删法
case TAIL:
//定义两个指针变量,一个初始化为头节点,一个初始化为首节点
pPre = pHead;
pDel = pHead->pNext;
if(NULL == pDel)
{
return EMPTY;
}
//判断pDel的指针域是否为空
while(pDel->pNext != NULL)
{
//两个指针同时向后移动
pPre = pDel;
pDel = pDel->pNext;
}
//保存要删除的数据
*pData = pDel->data;
//4.将pPre的指针域赋值为NULL
pPre->pNext = NULL;
//5.释放pDel
free(pDel);
pDel = NULL;
break;
//中间删除
default:
//定义两个指针变量,一个初始化为头节点,一个初始化为首节点
pPre = pHead;
pDel = pHead->pNext;
//当pDel不为空的情况下,移动pos-1次
while(pDel != NULL && i < pos-1)
{
pPre = pDel;
pDel = pDel->pNext;
i++;
}
if(NULL == pDel)
{
return EMPTY;
}
//保存好要删除的数据
*pData = pDel->data;
//保护好要删除节点后的所有节点
pPre->pNext = pDel->pNext;
//释放pDel
free(pDel);
pDel = NULL;
}
return OK;
}
5.销毁链表
int destroy_link(Link **pLink) //pLink = &pHead *pLink = pHead
{
//入参判断
if(NULL == *pLink)
{
return LINKNULL;
}
while(1)
{
//使用头删法的思想,对链表中的节点挨个进行删除,直到为空链表
//找到要删除的节点
Link *pDel = (*pLink)->pNext;
if(NULL == pDel)
{
break;
}
// 保护好要删除节点后的所有节点
(*pLink)->pNext = pDel->pNext;
//释放pDel
free(pDel);
pDel = NULL;
}
free(*pLink);
*pLink = NULL;
return OK;
}
这里要注意在传头节点地址的时候要用一个结构体二级指针接受,才能改变主函数里结构体指针的变化,完成置空的目的。
三,主函数及头文件
1.主函数
int main(void)
{
int op = 0;
int pos = 0;
data_type item = 0;
//定义一个指针变量
Link *pHead = NULL;
pHead = createLink();
while(1)
{
printf("请输入选项:\n");
printf("1---------------insertLink\n");
printf("2---------------showLink\n");
printf("3---------------deleteLink\n");
printf("4---------------destroyLink\n");
printf("-1--------------exit\n");
scanf("%d",&op);
if(-1 == op)
{
break;
}
switch(op)
{
case 1:
printf("请输入要插入的位置和数据:\n");
scanf("%d%d",&pos,&item);
insertLink(pHead,pos,item);
break;
case 2:
showLink(pHead);
break;
case 3:
printf("请输入要删除的位置:\n");
scanf("%d",&pos);
deleteLink(pHead,pos,&item);
printf("删除的数据为:%d\n",item);
break;
case 4:
printf("释放前:%p\n",pHead);
destroyLink(&pHead);
printf("释放后:%p\n",pHead);
break;
}
}
return 0;
}
2.头文件
#ifndef _LINK_H
#define _LINK_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int data_type;
typedef struct linkNote
{
data_type data;
struct linkNote *pNext;
}Link;
enum res
{
LINKNULL=-3,
MALLOCERROR,
EMPTY,
OK
};
enum op
{
TAIL=-1,
HEAD
};
//创建节点
Link *create_link(void);
//根据位置向链表插入元素
int insert_link(Link *phead,int pos,data_type item);
//显示
int show_link(Link *phead);
//根据位置删除链表的元素
int deleteLink(Link *phead,int pos,data_type *pdeta);
//销毁链表
int destroy_link(Link **pLink);
#endif