链表 二

本文围绕有头链表展开,由链表对象个数为0时的表示问题引出有头链表和无头链表。介绍了有头链表用固定头节点指代,头节点不包含有效数据,可简化操作。还阐述了有头链表的定义、添加对象、对象来源、遍历等内容,并对比了有头和无头链表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有头链表的构造
一个链表,当有N个对象串起来时,使用第一个对象来指代整个链表。
可以向链表中添加对象,也可以删除对象。
如果向链表中删除了所有对象,这个链表该怎么表示?(或者说,链表中有0个对象)
由这个问题引出了两种形式的表示方法:有头链表、无头链表。
有头链表与无头链表
无头链表:所有的节点都包含了有效数据。(上篇《链表一》当中演示的链表就是无头链表)
有头链表:用一个固定的头节点来指代整个链表,所有的对象挂在这个头节点下面,而头节点本身不包含有效数据。
有头链表:使用固定的链表头。(很容易表示对象个数为0的情形)

使用固定的头节点,是为了简化链表操作。
本篇介绍这种有头链表的使用
无头链表的缺点:没有固定的头节点,所有的节点都是数据节点。因此,当链表对象个数为0时,不好表示 。
(1)定义一个有头链表
只需要定义一个对象作为其节点,将成员next初始化为NULL。

Student m_head = {0, "head", NULL};

或者

Student m_head = {0};

当有对象加入时,直接加在它的后面就可以。
当它的next为NULL时,表示该链表一个对象也没有。
(也就是说,头节点自身只用于挂接,本身是不算作长度的)
(2)添加一个对象

void add(Student* obj)
{
	obj->next=m_head.next;
	m_head.next=obj;
}

链表中的对象,一般都动态创建的。
比如,当用户需要添加一个对象时,从控制台输入信息,然后创建一个对象,插入到链表中。也可以把对象附加到末尾

void add(Student* obj)
{
	Student* p=&m_head;
	while(p->next)
		p=p->next;//找到最后一个对象
	p->next=obj;//把obj挂在最后一个对象后面
	obj->next=NULL;//现在obj作为最后一个对象
}

(3)对象从哪来?
链表中的对象,一般都动态创建的。
(注意:动态创建的对象的生命期,自malloc之时生效,到free之后失效)

Student* obj = (Student*)malloc (sizeof(Student));
obj->id = 12;
strcpy(obj->name, "X");
add(obj);

对象的数据可以让用户来输入

// 用户输入数据
// 返回值:0表示成功;-1表示用户输入有误
int user_input(Student* obj)
{
	printf("学号:");
	scanf("%d",obj->id);
	printf("姓名:");
	scanf("%s",obj->name);
	return 0;
}

(4)有头链表的遍历
注意:在遍历有头链表时,不包含头节点本身

//遍历
void show_all()
{
	Student* p=m_head.next;
	while(p)
	{
		printf("ID:%d,name:%s\n",p->id,p->name);
		p=p->next;//下一个对象
	}
}

小结

  1. 比较了有头节点和无头节点
    (无头节点:当对象个数为0时,不太好表示)
  2. 有头节点的构造方法,动态创建对象,并加入到链表中。
#include <stdio.h>
#include <string.h>
#include <stdlib.h> 
struct Student
{	
int id;	
char name[16];	
Student* next;};
// 定义了一个有头节点
Student m_head = {0};
// 插入一个对象到链表中
void add(Student* obj)
{	
 obj->next = m_head.next; 	
 m_head.next = obj;
}
void add(Student* obj)
{	
 Student* p = &m_head;	
 while(p->next)		
 p = p->next;  // 找到最后一个对象
 p->next = obj;   //  把obj挂在最后一个对象后面	
 obj->next = NULL;  // 现在obj作为最后一个对象
 }  
 int main()
 {	
 Student* obj_1 = (Student*)malloc (sizeof(Student));	
 obj_1->id = 1;	
 strcpy(obj_1->name, "X");	
 add(obj_1); 	
 Student* obj_2 = (Student*)malloc (sizeof(Student));	
 obj_2->id = 2;	
 strcpy(obj_2->name, "Y");	
 add(obj_2);	
 return 0;
 }
#include <stdio.h>
#include <string.h>
#include <stdlib.h> 
struct Student
{	
int id;	
char name[16];	
Student* next;
};
// 定义了一个有头节点
Student m_head = {0}; 
// 插入一个对象到链表中
void add(Student* obj)
{
obj->next = m_head.next; 	
m_head.next = obj; 
} 
void add(Student* obj)
{	
Student* p = &m_head;
while(p->next)		
p = p->next;  // 找到最后一个对象	
p->next = obj;   //  把obj挂在最后一个对象后面	
obj->next = NULL;  // 现在obj作为最后一个对象
}
 // 用户输入数据
 //返回值:0表示成功;-1表示用户输入有误
 int user_input(Student* obj)
 {	
 printf("学号: ");	
 scanf("%d", &obj->id);	
 printf("姓名: ");	
 scanf("%s", obj->name);	
 return 0;
 }  
 int main()
 {	
 while(1)	
 {		
 Student* obj_1 = (Student*)malloc (sizeof(Student)); 
 if(user_input(obj_1) == 0)		
 {			
 add(obj_1);		
 }		
 else		
 {			
 free(obj_1);		
 }				
} 	
 return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值