注:在实验时,受编译器种类限制,某些代码须稍加修正
一、创建
头插法:
①什么是头插法?
②代码实现:
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node * next;
}Node;
//create函数如下:
Node*create(int n)
{
int i;
Node*head= (Node*)malloc(sizeof(Node)); //创建头节点
head->next=NULL;
for(i=0;i<n;i++)
{
Node*p=(Node*)malloc(sizeof(Node));
scanf("%d",&(p->data));
p->next=head->next;
head->next=p;
}
return head;
}
//visit函数如下
void visit(Node*head)
{
head=head->next;
while(head!=NULL)
{
printf("%d\n",head->data);
head=head->next;
}
}
int main(void)
{
int num;
scanf("%d",&num); //输入想要创建节点的个数
Node*head=create(num);
visit(head);
return 0;
}
输出结果:
很明显头插法是逆序输出的
尾插法:
①什么是尾插法?
②代码实现:
//create函数如下:
Node * create(int n)
{
int i;
Node * head= (Node*)malloc(sizeof(Node)); //创建头节点
head->next=NULL;
Node*fakehead=head; //创建虚拟头节点代替真实的头节点
for(i=0;i<n;i++)
{
Node*p=(Node*)malloc(sizeof(Node));
scanf("%d",&(p->data));
p->next=NULL;
fakehead->next=p;
fakehead=p;
}
return head;
}
输出结果:
很明显尾插法是正序输出的
两者的差别在哪呢?
除了输出逆序正序外,两者执行过程中用来表示头节点的head变量的变化也是不同的。
头插法中,head变量存储的值(头节点的地址)是固定的。p变量存储的值一直变动。
尾插法中,head变量和p变量是一直变化的,(由于函数返回值是头节点的指针,head变化后则无法返回正确值,所以用fakehead代替head)这种情况就好像移动。
二、添加
①如何添加?
找到值为x节点的地址,在其前面或后面插入新的节点。
②前插代码实现
Node * add(Node*head)
{
int n;
printf("你想在哪个数字前面添加:");
scanf("%d",&n);
Node*newnode=(Node*)malloc(sizeof(Node)); //创建要插入的节点
printf("输入你想添加的数字:");
scanf("%d",&newnode->data);
Node*fakehead=head;
Node*pre;
while(fakehead!=NULL&&fakehead->data!=n)
{
pre=fakehead;
fakehead=fakehead->next;
}
pre->next=newnode;
newnode->next=fakehead;
return head;
}
输出结果:
③代码解释,以前插为例:
fakehead->data已经等于所要寻找的x,此时将要插入的节点在pre和fakedata之间插入。
如果想要后插入只需稍稍变动:
//add函数如下
Node * add(Node*head)
{
int n;
printf("你想在哪个数字后面添加:");
scanf("%d",&n);
Node*newnode=(Node*)malloc(sizeof(Node));
printf("输入你想添加的数字:");
scanf("%d",&newnode->data);
Node*fakehead=head;
Node*pre;
while(fakehead!=NULL&&fakehead->data!=n)
{
pre=fakehead;
fakehead=fakehead->next;
}
newnode->next=fakehead->next; //改动部分
fakehead->next=newnode; //改动部分
return head;
}
同样还是fakehead的位置是x的位置,在fakehead的后面插入一个新的节点。newnode>next=fakehead->next;
fakehead->next=newnode;
这两行代码和创建链表中的头插法是一样的。
输出结果:
三、删除
①怎样删除链表里的节点?
我们找到所要删除的节点x,然后将x前一个节点的next赋值为x后一个节点的地址。
②代码实现:
Node * del(Node*head)
{
int n;
printf("你想删除的数字是:");
scanf("%d",&n);
Node*fakehead=head;
Node*pre;
while(fakehead!=NULL&&fakehead->data!=n)
{
pre=fakehead;
fakehead=fakehead->next;
}
pre->next=fakehead->next;
return head;
}
输出结果:
③代码解释
这里和前面add函数(链表的添加)差不多,依然是采用了fakehead和pre。一前一后,当fakehead是寻找的x时,pre的next直接赋值为fakehead下一个节点的地址。
一个小细节是x的next还保存的还是data4的地址。