目录
1 创建链表和打印
创建链表的图为下图:
利用结构体,创建一个单向链表。这里的使用和柔性数组类似,把数组换成了指针。具体的过程如下代码所示:
typedef struct node
{
int data;
struct node* next;
}NODE;
NODE* creat()
{
NODE* head, * p, * q; //创建头指针
int t;
head = malloc(sizeof(NODE));
if(!head) //判断是否在堆上开辟出空间
return NULL;
p = head; //记录头指针的地址
while (1)
{
printf("输入一个正整数(以负数结束):");
scanf_s("%d", &t);
if (t < 0) //链表结点值不为负数
break;
q = malloc(sizeof(NODE));
if (!q)
return NULL;
q->data = t; //利用指针连接两个指针
p->next = q;
p = q;
}
p->next = NULL;
return head;
}
void print(NODE* head) //利用传值调用打印链表
{
NODE* p=NULL;
p = head->next;
if (!p) //保证链表不为空
printf("该链表为空!\n");
else
{
printf("链表中的数据为:\n");
while (p != NULL) //指针指向最后的空指针时,跳出循环
{
printf("->%d", p->data);
p = p->next;
}
printf("\n"); //全部打印完之后进行换行
}
}
int main()
{
NODE* h;
int data=0;
h = creat(); //将链表创建出来
print(h); //打印显示链表
return 0;
}
2 链表某一结点删除
2.1使用双指针定位
具体的过程代码已注释:
void dele(NODE* head, int t) //将链表的头指针和需要删除的值拷贝一份进来
{
NODE* p=NULL, * q=NULL;
q = head; //使用q代替head指针
p = head->next; //使用p指向下一个节点
while (p!= NULL) //保证第一个结点有值,只需看指针是否为空即可
{
if (p->data == t) { //当第一个结点为要删除的值时
q->next = p->next; //找到那个值后,将下一个结构体地址赋值给上一个结构体指针
free(p); //把要删除的值对应的结构体指针释放
break;
}
else //设置两个指针在链表中挨着移动,访问链表中的每一个值
{
q = p;
p = p->next;
}
}
if (!p) //找不到对应要删除的值时
printf("无符合条件的结点!!!\n");
}
2.2 使用单指针
我们要特别注意函数
h
ead
是一
个
指针,由于结点的删除涉及到链表的修改。所以,想到使用二级指针的函数来删除链表的某一个结点。
代码过程如下,必要的代码后面附有必要的注释,提高了代码的可读性:
void dele(NODE** head, int value)
{
if (!head || !(*head)) //保证传进来指针不为空指针
return;
NODE* pToBeDeleted = NULL; //使用一个指针记录对应值的结构体地址
if ((*head)->next->data == value) //第一个结点是否为删除的值
{
pToBeDeleted = (*head)->next;
(*head)->next = (*head)->next->next;
}
else
{
NODE* pNode = (*head)->next; //[注意]这里代码若为NODE* pNode = *head;的话,会改变链表的数据。 这里使用的是传址调用。
while (pNode->next != NULL && pNode->next->data != value) //使用一个指针不断移动寻找所要删除的值,找不到则跳出此循环
{
pNode = pNode->next;
}
if (pNode->next != NULL && pNode->next->data == value)
{
pToBeDeleted = pNode->next; //记录要删除的结点地址
pNode->next = pNode->next->next; //找到那个值后,将下一个结构体地址赋值给上一个结构体指针,将链表串联起来
}
if (pNode->next==NULL) //注意此指针的起始位置 不要盲目不断的尝试,多看内存
printf("此链表无此值!!!\n");//如果找不到,打印输出
}
if (pToBeDeleted != NULL) //释放要删除的结点地址,防止内存泄漏
free(pToBeDeleted);
}
3 创建链表与删除某个结点
这里想到在VS控制台输出时,输入一系列值创建一个链表并打印出来,同时可以删除链表中的值。于是将上面代码进行合并。
主函数:
int main()
{
NODE* head;
head=Creat();
print(head); //打印函数
int value = 0;
while (1)
{
printf("请输入需要删除的值为(以负数为结束标志):"); //使用负数为结束输入标志
scanf_s("%d", &value);
if (value<0) //使用负数为结束输入标志
break;
dele(&head, value); //传入头函数的地址和要删除的值
print(head);
}
return 0;
}
调用的函数代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node* next;
}NODE;
NODE* Creat()
{
NODE* pone, * ptwo;
pone = NULL;
ptwo = NULL;
NODE* head = malloc(sizeof(NODE));
if (!head)
return NULL;
pone = head;
int data=0;
while (1)
{
ptwo = malloc(sizeof(NODE));
if (!ptwo)
return NULL;
printf("请输入链表中结点的值(以负数为结束标志):");
scanf_s("%d", &data);
if (data<0)
break;
ptwo->data = data;
pone->next = ptwo;
pone = ptwo;
}
pone->next = NULL;
return head;
}
void print(NODE* head)
{
NODE* p ;
p= NULL;
p = head->next;
if (!p)
printf("该链表中的数据为空!!!\n");
else
{
printf("该链表中的数据为:\n");
while(p!= NULL) //全部打印完
{
printf("->%d", p->data);
p = p->next;
}
printf("\n");
}
}
void dele(NODE** head, int value)
{
if (!head || !(*head))
return;
NODE* pToBeDeleted = NULL;
if ((*head)->next->data == value) //第一个结点是否为所要的真值
{
pToBeDeleted = (*head)->next;
(*head)->next = (*head)->next->next;
}
else
{
NODE* pNode = (*head)->next; //[注意]这里代码若为NODE* pNode = *head;的话,会改变链表的数据。
while (pNode->next != NULL && pNode->next->data != value)
{
pNode = pNode->next;
}
if (pNode->next != NULL && pNode->next->data == value)
{
pToBeDeleted = pNode->next;
pNode->next = pNode->next->next;
}
if (pNode->next==NULL) //注意此指针的起始位置 不要盲目不断的尝试,多看内存
printf("此链表无此值!!!\n");
}
if (pToBeDeleted != NULL)
free(pToBeDeleted);
}
结果如下:
以上代码均已调试,若有其他问题,请在评论区打出。