链表的插入与删除

一,实现功能

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

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值