有头单链表操作

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
// struct Node
//{
//	DataType data;
//	struct Node*next;
//};
// typedef struct Node NODE, *LPNODE;
//删除节点才需要先连接,后释放;插入:先新节点连接下一个(原本当前节点)||先前驱节点连接新节点,都可以正常运行
//反转、合并等未做
typedef struct Node
{
	DataType data;
	struct Node*next;
}NODE, *LPNODE;//链表结构体描述

//创建表头(的模板):头节点数据域一般不存放有用数据(可能存储链表有多少节点,需要再单独创造函数计算并给予赋值),这里不做初始化处理,而指针域指向NULL(赋空),因为头节点最初是不连接节点,整个链表为空链表
LPNODE createHead()
{
	LPNODE headNode = (LPNODE)malloc(sizeof(NODE));
	headNode->next = NULL;
	return headNode;
}

//创建其他节点(的模板):结构体的至少两种变量(指针域,数据域,数据域其实在一个结构体中可以有多种且多个)
LPNODE createHead(DataType data)//这里与创建头节点的函数构成重载
{
	LPNODE newNode = (LPNODE)malloc(sizeof(NODE));
	assert(newNode);//断言函数,如果判断语句为假,返回错误信息,并结束程序
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}

//再次提醒:函数名,结构体名,数组名等它们本身名字就是地址,无需&符号


//有头头插,每次插入在头节点后方,链表是先进后出
void insertNode(LPNODE headNode, DataType data)
{
	LPNODE newNode = createHead(data);        //1.创建出来
	newNode->next = headNode->next;           //新节点先连接原本头节点的下一个(新节点指针域next存放头节点指针域存放的下一个节点地址)
	headNode->next = newNode;                 //头节点的下一个修改为新节点     (头节点指针域next存放修改为新节点的地址)
}

//有头尾插,需要每次遍历找到指针域为空的节点(此时头节点的指针域已经新节点的地址所赋值不在指向NULL)
void  insertTail(LPNODE headNode, DataType data)
{
	LPNODE newNode = createHead(data);        //创建出来
	LPNODE pmove = headNode;                  //调用链表节点,此次从头节点开始,以防止此链表为空链表(此时尾插等同于头插);
	while (NULL != pmove->next)
	{
		pmove = pmove->next;
	}
	pmove->next = newNode;                     //原本尾节点指针域next被赋值为新节点的地址,新节点成为新的尾节点
}
//有头按数据插入,需要前驱/后继节点确定位置与存放位(如放第N位置的前/后)
void insertselect(LPNODE headNode, DataType posData, DataType data)
{
	LPNODE preNode = headNode;                  //前驱节点
	LPNODE curNode = headNode->next;            //当前节点

	//查找
	while (NULL != curNode->data&&posData != curNode->data)                       //遍历查找数据符合的节点,且必需先判断节点数据不为空(利用短路特性使程序不出现空值错误)
	{
		/*preNode = preNode->next;
		curNode = curNode->next;*/
		preNode = curNode;
		curNode = curNode->next;
	}

	//分析结果
	if (NULL == curNode)
	{
		printf("无法进行插入,因为没有指定数据");
	}
	else
	{
		LPNODE newNode = createHead(data);
		preNode->next = newNode;
		newNode->next = curNode;
	}
}

//有头按位置插入
void insertloca(LPNODE headNode, DataType location, DataType data)
{
	LPNODE proNode = headNode;
	LPNODE curNode = headNode->next;
	DataType count = 0;
	while (count!=location&&NULL!=curNode->next)//跳出此语句的两种条件(curNode->next==NULL||count==location)在下方进行处理,
	{
		proNode = curNode;
		curNode = curNode->next;
		count++;
	}
	if (NULL ==curNode)
	{
		printf("无法进行插入,原因为没有指定位置");
	}
	else//按位置插入必须在原本此位置节点前面插入
	{
		LPNODE newNode = createHead(data);//先创建新节点
		newNode->next = curNode;
		proNode->next = newNode;
	}

}

//有头头节点(第一个节点\头节点)删除
void delectNode01(LPNODE headNode)
{
	LPNODE frontNode = headNode->next;              //查询当前节点,从头节点next开始查询
	if (NULL == frontNode->data)
	{
		printf("链表为空,无法删除");
	}
	else
	{
		headNode->next = frontNode->next;
		free(frontNode);
		frontNode = NULL;
	}
}

//有头尾节点(最后个节点\尾节点)删除
void delectNode02(LPNODE headNode)
{
	LPNODE proNode = headNode;                     //前驱节点
	LPNODE backNode = headNode->next;                    //查询当前节点,从头节点next开始查询
	while (NULL != backNode&&NULL!=backNode->next)
	{
		proNode = backNode;
		backNode = backNode->next;
	}
	if (NULL == backNode)
	{
		printf("链表为空,无法删除");
	}
	else
	{
		free(backNode);
		backNode = NULL;
		proNode->next = NULL;
	}
}

//删除指定数据
void delectNode03(LPNODE headNode,DataType posData)
{
	LPNODE proNode = headNode;
	LPNODE curNode = headNode->next;
	//先查找
	while (NULL != curNode->data&&posData != curNode->data)                       //遍历查找数据符合的节点,且必需先判断节点数据不为空(利用短路特性使程序不出现空值错误)
	{
		/*preNode = preNode->next;
		curNode = curNode->next;*/
		proNode = curNode;
		curNode = curNode->next;
	}
	if (NULL == curNode)
	{
		printf("链表为空,无法删除");
	}
	else
	{
		proNode->next = curNode->next;
		free(curNode);
		curNode = NULL;
	}
}

//删除指定位置
void delectNode04(LPNODE headNode, DataType location)
{
	LPNODE proNode = headNode;
	LPNODE curNode = headNode->next;
	DataType count = 0;
	while (location != count)
	{
		proNode = curNode;
		curNode = curNode->next;
		count++;
	}
	if (NULL== proNode)
	{
		printf("链表为空,无法删除");
	}
	else
	{
		proNode->next = curNode->next;
		free(curNode);
		curNode = NULL;
	}
}

//修改指定数据
void hackappointdata(LPNODE headNode,DataType hackdata,DataType data)
{
	LPNODE curNode = headNode->next;
	while (NULL != curNode&&hackdata != curNode->data)
	{
		curNode = curNode->next;
	}
	if (NULL == curNode)
	{
		printf("链表已到尽头,未查找到指定数据\n");
	}
	else
	{
		curNode->data = data;
	}
}

//修改指定位置
void hackappointloca(LPNODE headNode, DataType location, DataType data)
{
	LPNODE curNode = headNode->next;
	DataType count = 1;
	while (NULL!=curNode&&location!=count)
	{
		curNode = curNode->next;
		count++;
	}
	if (NULL == curNode)
	{
		printf("链表没有本次指定的位置,故无法完成修改");
	}
	else
	{
		curNode->data = data;
	}
}
LPNODE searchNode(LPNODE headNode, DataType posData)    //按数据查找
{
	LPNODE pmove = headNode;
	while (pmove != NULL&&pmove->data != posData)
	{
		pmove = pmove->next;
	}
	return pmove;
}

//打印链表的数据
void printfList(LPNODE headNode)
{
	LPNODE pmove = headNode->next;            //调用链表节点,且头节点现在设置的是NULL,所以从头节点的下一个开始打印
	while (pmove)
	{
		printf("%d\t",pmove->data);
		pmove = pmove->next;
	}
	printf("\n");
}
int main()
{
	LPNODE list = createHead();               //调用创建头节点的函数

	for (int i = 0; i < 5; i++)               //调用头插其余节点的函数
	{
		insertNode(list, i);
	}
	printfList(list);                         //调用打印链表的函数

	insertTail(list, 666);                    //调用尾插其余节点的函数
	printfList(list);                         //调用打印链表的函数

    insertselect(list, 4, 5);                 //调用按数据插入
	printfList(list);                         //调用打印链表的函数


	insertloca(list,7, -1);                   //调用按位置插入
	printfList(list);                         //调用打印链表的函数


	delectNode01(list);                       //调用表头删除的函数
	printfList(list);                         //调用打印链表的函数

	delectNode02(list);                       //调用表尾删除的函数
	printfList(list);                         //调用打印链表的函数

	delectNode03(list,0);                      //调用按数据删除的函数
	printfList(list);                         //调用打印链表的函数

	delectNode04(list, 1);                      //调用按位置删除的函数
	printfList(list);                         //调用打印链表的函数

	hackappointdata(list, -1, 7);             //调用按数据修改的函数
	printfList(list);                         //调用打印链表的函数
	
	hackappointloca(list, 4, 0);             //调用按位置修改的函数
	printfList(list);                         //调用打印链表的函数

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值