#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;
}
有头单链表操作
最新推荐文章于 2022-11-07 20:07:46 发布