单链表的增、删、改、逆转,详细

 手动写一个链表,之前很顺畅,这次不知因为什么卡了好久,看明白之后对你很有帮助,最起码简单的链表可以自己解决了,仔细的琢磨一下,不懂的就自己手动画画图,自己画懂才是硬道理。

正文

#include<stdlib.h>
int count =0; 			   	        //计算链表内的节点个数
typedef struct SNode				//定义结构体
{
	int data;                		//数据域,存储数据
	struct SNode *next;	  		//指针域,存储下一个节点的地址
}Link;			
Link* GetLink()                 	        //创造头节点并返回
{
	Link *p = (Link*)malloc(sizeof(Link));	//在堆内存上开辟一块空间,防止消失
	if ( NULL == p ) {			//如果开辟失败为NULL
		printf("malloc error\n");       //打印错误信息
		return NULL;       		//返回没必要继续执行
	}
	p->next=NULL;				//如果开辟成果初始化
	p->data=0;
	return p;				//返回地址
}
void AddMember(Link *p,int data)                //添加成员
{
	while( p->next != NULL )               	//找到链表的末尾
	{
		p=p->next;			//不断的循环去找下一个节点,直到最后一个节点
	}
	Link *q;		
	q = (Link*)malloc(sizeof(Link));	//创建一个新的节点
	if ( NULL == q )			//对新节点进行判断,是否开辟成功
	{
		printf("AddMember malloc error\n"); //没成功打印错误信息
		return;				//返回,不需要继续执行;
	} 
	q->data = data;				//初始化新节点
	q->next = NULL;				//新节点没有下一个节点,所以next为NULL
	p->next = q;				//链表的最后一个节点指向新节点
	count++;				//计数变量自增1
}
void Print(Link *p)		                //遍历链表
{
	while(p->next!=NULL)			//当p没有下一个节点时候退出循环
	{
		p = p->next;			//由于有头节点GetLink()创建的,所以跳过头结点
		printf("%d\n",p->data);		//打印数据域
	}
}
void RemovData(Link *p,int data) 		//删除数据
{
	while( p->next != NULL )		//当p没有下一个节点时候退出循环
	{
		if( p->next->data == data )     //p的下一个节点的数据域是想删除的数据
		{
			break;
		}
		p=p->next;			//如果不break,p会一直向下走
	}
	if(p->next = NULL)			//如果走到最后没有找到,p->next为NULL代表最后一个节点
	{
		printf("没有对应的数据:%d,删除失败\n",data);//打印没找到信息
		return;				//结束函数,没必要继续向下执行
	}
	Link *q = p ->next;			//创建一个新节点为p的下一个节点(所删除的节点)
	p->next = q->next;			//令链表跳过所删除的节点,直接指向所删除节点的下一个节点
	free(q);				//释放掉所删除的节点(由于是在堆上开辟的空间)
	count--;
}
void ChangeData(Link *p,int pos,int data)	//修改指定位置的数据
{
	int i=0;				//i为计算走的步数
	if(pos>count)				//如果所改变的位置大于节点个数不符合规范
	{
		printf("pos error\n");		//打印错误信息
		return;				//结束函数
	}
	for(i=0;i<pos+1;i++) 			//由于头节点为空所以多走一步
	{
		p = p->next;			//p不断向下一个节点移动
	}
	p->data=data;				//修改数据域
}
void Reverse(Link *h)				//链表逆转
{					//链表反转,这里需要借助两个临时的Link变量,如果有不理解的小伙伴
				//可以先琢磨其他部分,然后在研究这里。理解之后不难的,自己画图按照逻辑画一遍;
	Link *h,*q;
	p=h->next;		//p在头部的下一个节点,想要逆转需要把链表的头部变成尾部,h作为头结点不改变位置
	q=p;			//q和p在同一节点,为头结点的下一个节点
	h->next=NULL;		//先断开头结点
	while(q)
	{
		q=q->next;	//这句我不明白为啥非要放在这我才会正常运行,向下挪一行都不行,只是用作判断是否为最后一个节点。
		p->next = h->next;	//p->next指向h的next;
		h->next = p;		//h->next指向p所在的节点		
		p=q;			//p到q的位置
	}
	
}
int main()
{
    Link *p = GetLink();
    if( NULL == p )
    {
    	printf("GetLink error\n");
    	return -1;
    } 
    AddMember(p,5);
    AddMember(p,4);
    AddMember(p,3);
    AddMember(p,2);
    AddMember(p,1);
    ChangeData(p,3,10)
    Print(p);
    printf("------------------\n");
    Reverse(p);
    Print(p);
    printf("------------------\n");
    RemovData(p,30);
    RemovData(p,5);
    RemovData(p,1);
    Print(p);
 }
输出结果为
5
4
3
10
1
------------------
1
10
3
4
5
------------------
没有对应的数据 30
10
3
4
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值