//输入字符,尾插法建立链表。$ 结束
//头结点,数据域存储总的节点数
Linklist * creat_node()
{
Linklist *head,*p,*r;
int i=0;//字符计数
char ch;
ch=getchar();
r=(Linklist *)malloc(sizeof(Linklist));
head=r;
while(ch!='$')
{
p=(Linklist *)malloc(sizeof(Linklist));
p->data=ch;
i++;//字符计数从1开始
r->next=p;
r=p;
ch=getchar();
}
head->data=i;//字符数放入头结点中
return head;
}
通过调试可以看到输入 25648$ 形成单链表的结构图,p,p->next存的都是下一个节点的地址值,用指针方式,通过这个地址值来访问节点内存
一、查
(1)按序号查
//返回节点,就是结点的首地址
Linklist * get_node(Linklist * head,int i)
{
if(i>head->data)
{
printf("序号超出范围");
}
else
{
while(i)
{
head=head->next;
i--;
}
}
return head;
}
(2)按值查
//返回节点,就是结点的首地址
//按值查
Linklist * get_x_node(Linklist * head,int x)
{
Linklist * p;
int i=head->data;
int j=1;
x=x+48;
p=head->next;//从第一个结点开始查找
while((p->data!=x)&&(j<=i))
{
p=p->next;
j++;
}
if(j>i)
printf("没有这个结点");
return p;
}
二、增
//插入值为x,位置序号为i,前插比较麻烦建议后插法
Linklist * insert_node(Linklist * head,int i,int x)
{
Linklist * p,*q;
p=get_i_node(head,i);//调用前面的函数,得到序号i的节点地址
//后插法
q=(Linklist *)malloc(sizeof(Linklist));//生成新节点
q->data=x;
p->next=q;//i节点指向新节点
q->next=p->next;//新节点指向i+1节点
/* 对于第一个结点问题没解决
//前插法 没有前驱指针,只能重找一次,使下一个节点地址等于p。
//查值法,找节点。
Linklist * p,*q,*s;
p=get_x_node(head,x);//调用前面的函数,得到值为x的节点地址
q=head->next;
while(q->next!=p)
{
q=q->next;
}
s=(Linklist *)malloc(sizeof(Linklist));//生成新节点
s->data=x;
s->next=p;//i-1节点指向新节点
q->next=s;//新节点指向i节点
*/
return head;
}
三、删
//删除第i+1个结点,即i后面一个的结点
//找到后释放结点
Linklist * delete_node(Linklist * head,int i)
{
Linklist * p,*q;
p=get_i_node(head,i);//调用前面的函数,得到序号i的节点地址
q=p->next;//得到i+1个结点首地址
p->next=q->next;//把i+1结点的指针域给第i个结点的指针域。
free(q);//释放q结点
return head;
}
删除失败,调试过程
删除原函数
//删除第i+1个结点,即i后面一个的结点
//找到后释放结点
Linklist * delete_node(Linklist * head,int i)
{
Linklist * p,* q;
p=get_i_node(head,i);//调用前面的函数,得到序号i的节点地址
q=p->next;//得到i+1个结点首地址
p->next=q->next;//把i+1结点的指针域给第i个结点的指针域。
free(q);//释放q结点
return head;
}
第三个结点显示正常,我们要删除 0x002c07b8
进行删除,没有成功。 看了原代码,没错啊,好像free失效一样。
这里我重新输入了一下,所以地址变了。现在要删除 0x003f07b8 的57
那进入函数内部看看吧
现在得到第三个结点地址p
可以看到第三个结点地址,p=0x003f0770,我们要删除它的下一个节点。也就是0x3f07b8
下一步
把p的下一个节点 0x3f07b8 给q=0x3f07b8
现在q=0x3f07b8 就是我们要删除的结点首地址
然后再把q=0x3f07b8的下一个结点 0x003f0800 给p->next
可以看到这也是对的
q=0x3f07b8结点删除成功了。那就是显示的问题了。
head2是head1的第三个结点,值为54
对比一下,两个图,确实删除了head1的第三个结点,现在第三个结点现在值为56
好吧现在是正常的,刚刚见鬼了。就当看一下调试过程,熟悉内部结构吧。