数据结构(C语言版) 代码详解01-单链表

#include<stdio.h>
#include<stdlib.h>//动态分配空间头文件 

/***创建链表的结构体:
链表中第一个结点数据data存的是链表目前的结点个数
next是个结构体指针 指向下一个结点的地址

第一个结点是头结点 不是读入进去的数据 
***/
typedef struct Node{
	int data;
	struct Node* next;
}Node;//通过typedef的方式将访问链表的方式进行重定义 可以参考: https://blog.csdn.net/sjp151/article/details/119668876 

/***初始化链表: 
1、 要给链表开辟一块新的内存空间/创建新结点 
2、 将链表结点清空(个数为0、头节点的下一个结点为空) 
	abbr. 初始化(initialization) 
***/
Node* initList(){//这里返回的应该是头结点的地址(指针) 
	//因为只要得到头结点的地址,就可以知道其他的结点
	
	Node* L=(Node*)malloc(sizeof(Node));
	L->data=0;
	L->next=NULL;
	return L;
}

/***头插法:
1、需要传递头结点和插入的数据
2、创建一个新结点
3、将数据赋给新结点data

4、将头结点的next赋给新结点的next:new->next=L->next
	解释:头结点在第一次执行头插法时为空,则新结点的下一个结点地址为空(还没有插入第二个新结点)
5、将新结点的地址赋给头结点的地址(不是next):L->next=new
	解释:在插入第一个新的结点时 头结点的下一个结点地址next就是新结点的地址(这里不是next,next是新结点的下一个结点) 
		在第2次插入新结点的时候, 新的结点的next是头结点的next(也就是插入的第一个结点地址)
		头结点的next就变成新结点的地址,如下方演示:
		未插入第二个结点前:L->data=1 L->next=new1 new1->next=NULL
		插入第二个结点后:  L->data=2 L->next=new2 new2->next=new1 new1->next=NULL
		...
6、头结点的data++(代表此时链表的结点增加一个)	 
***/ 

void headInsert(Node* L,int data){//L本身存储的就是地址 
	Node* node=(Node*)malloc(sizeof(Node));
	node->data=data;
	node->next=L->next;
	L->next=node;
	L->data++;
}

/***尾插法:
1、同样需要 头结点地址和数据
2、创建一个结点等于头结点 new=L 用于遍历链表 
3、遍历链表,得到当前链表最后一个结点的地址 
4、开辟一块内存空间给新插入的结点,将data赋值,next置为空,链表原来的最后一个结点的next=新结点的地址
5、头结点的data++ 
***/

void tailInsert(Node* L,int data){
	Node* node=L;//为了防止遍历过程中头结点改变 要用新的结点来遍历链表 
	for(int i=0;i<L->data;i++){
		node=node->next;
	}
	Node* n=(Node*)malloc(sizeof(Node));
	n->data=data;
	n->next=NULL;
	node->next=n; 
	L->data++;
}
	/***
	假设原来的链表为 2 111,1 112,2 113 (111是头结点,剩下的是自带的结点)
	node=111
	node=112
	node=113 
	这样就可以得到链表的最后结点 
	***/

/***删除结点:
1、找到要删除的结点,将上一个结点的next赋值为下一个结点的地址
	上一个结点->next=删除结点->next
2、释放要删除的结点 结点个数--
3、找到目标结点删除 返回真 没找到返回假 
***/

int deletedata(Node* L,int data){
	//delete在devc++是关键字 
	
	//这里类似于 双指针的用法? 
	Node* preNode=L;//以头结点为开始
	Node* node=L->next;//第一个数据结点的地址
	
	while(node){
		if(node->data==data){
			preNode->next=node->next;
			free(node);
			L->data--;
			return 1;
		}
		preNode=node;
		node=node->next;
	} 
	return 0; //0为假 非0为真 
}

/***打印链表:
遍历链表 
***/ 

void printList(Node* L){
	Node* node=L->next;//指向第一个数据结点 而不是头结点 
	while(node){
		printf("%d ",node->data);
		node=node->next;
	}
} 

int main(){
	//建立链表并且初始化它
	Node* L=initList();
	headInsert(L,1);//头插法,传递 创建好的链表 和 值
	headInsert(L,2);
	headInsert(L,3);
	headInsert(L,4);
	headInsert(L,5);
	tailInsert(L,6);//尾插法 
	tailInsert(L,7);
	tailInsert(L,8);
	tailInsert(L,9);
	tailInsert(L,10);
	printList(L);//打印链表
	
	if(deletedata(L,10)){
		printf("删除成功\n");
	}
	else{
		printf("删除失败\n");
	}
	
	printList(L);//再打印一遍链表 
	return 0;
}

学习文件来自数据结构系列2-单链表 | tyrantlucifer

  • 14
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值