C语言数据结构拦路虎(五)-单链表的查,增,删

//输入字符,尾插法建立链表。$ 结束
//头结点,数据域存储总的节点数
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

好吧现在是正常的,刚刚见鬼了。就当看一下调试过程,熟悉内部结构吧。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大大U

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值