结构体类型数据的动态存储分配和链表及其基本操作

1.结构体类型数据的动态存储分配

一.前言

c语言提供了一些内存管理函数,用于动态分配内存空间(堆区).可以根据需要开辟内存的单元,在程序执行时,需要多少空间就分配多少内存空间,且当空间不再使用还可以释放

二.关于内存空间的函数

在有操作系统和虚拟地址管理情况下,一次malloc的内存虚拟地址是连续的物理地址不连续,连续多次malloc的内存之间不连续,应该说不一定连续
1.分配内存空间函数malloc
(类型说明符*)mallloc(size)
功能:在内存的动态存储区中分配一片长度为size字节的连续区域.如果分配成功,就返回所分配空间的起始地址;如果分配失败,就返回空指针NULL。
说明

  • “类型说明符” 表示该区域
  • (类型说明符*)表示把返回值强制转换为该类型指针。
  • size是一个无符号整数

例如
pc=(char *)malloc(80);
表示分配80个字节的内存空间,空间首地址强制转换为指向字符的指针,并赋予指针变量pc.
2.释放内存空间函数calloc
调用形式为
free §;
功能:释放p指向的内存空间,由系统回收。

2.链表实例

#include
#include
struct student
{
	long num;
	float score;
	struct student *next;
};
struct student *creat(int n); //创建链表 
//这里struct student是类型,*表示是指针,也就是说函数create()返回值是一个struct student
类型的指针。
void print(struct student *head);//链表遍历 
struct student *del(struct student *head,int num); //删除链表中的一个节点 
//这里struct student是类型,*表示是指针
//也就是说函数create()返回值是一个struct student类型的指针。
struct student *insert(struct student *head,struct student *stud);//链表的插入	
int main(void)
{
	//创建一个链表 
	struct student *phead=NULL;
	phead=creat(3);
	print(phead);//遍历链表 
	
	//链表中节点删除一个节点 
	printf("Please enter the num to delete:");
	int n=0;
	scanf("%d",&n); 
	print(del(phead,n)); //删除一个节点后并遍历 
	
	//链表中插入一个节点 
	struct student stud;
	printf("\nPlease input the num to insert: ");
	scanf("%d,&stud",&stud.num);
	printf("Please input the score:");
	scanf("%f",&stud.score); 
	print(insert(phead,&stud));//节点插入并遍历 
	
}
struct student *creat(int n)//创建链表 
//这里struct student是类型,*表示是指针,也就是说函数create()返回值是一个struct student
类型的指针。
	{
	struct student *head=NULL,*p1,*p2;
	head=p2=(struct student *)malloc(sizeof(struct student));//101开辟第一个节点,并使p2和head都指向它 
	printf("请输入学号 分数\n");
	scanf("%ld  %f",&p2->num,&p2->score);
		for(int i=2;i<=n;i++)
		{	
		p1=(struct student *)malloc(sizeof(struct student));
		//for语句第一轮循环相当于开辟第二个节点 
		scanf("%ld %f",&p1->num,&p1->score);
		p2->next=p1; //与上一节点相连 
		p2=p1; //使p2指向新连节点 
		}
		p2->next=NULL;
		return(head);
	}
void print(struct student *head)//链表遍历 
	{
	struct student *p;
	p=head;//先使p指向结构体指针 
	while(p!=NULL)
	 {
	 	printf("%d %f\n",p->num,p->score);
	 	p=p->next;//巧妙转换先使p指向结构体指针,再让p访问结构体成员变量指针其保留下一个指向结构体的指针,然后再让其访问结构体成员指针 
	 }
	}
struct student *insert(struct student *head,struct student *stud)//链表的插入
//待会完成 
//第一个参数需要被插入的链表 第二个参数待插入的结构的地址 
{
	struct student *p1,*p2=NULL,*ptr;
	p1=head;
	ptr=stud;
	if(head==NULL)//如果链表是空表 
	{
		head=ptr;
		ptr->next=NULL;
	}
	else
	{
		while((ptr->num>p1->num)&&(p1->next!=NULL))
		//两种情况退出循环while 
		
		{
			p2=p1;
			p1=p1->next;
		}
		if(ptr->num<=p1->num)
		{
			if(head==p1)//节点插入到表头 
			{
				head=ptr;
			}
			else
			{
				p2->next=ptr;//节点插到表中间; 
			} 
			ptr->next=p1;
		}
		//第二种情况p0的num最大 ,插入到尾部 
		else//节点插入链表尾部 
		{
			p1->next=ptr;
			ptr->next=NULL;
		} 
	}
	return(head);
}	
struct student *del(struct student *head,int num)//删除链表中的一个节点 
{
	struct student *p1,*p2=NULL;
	if(head==NULL)//如果头节点指向NULL,这是一个空链表.纯属忽悠 
	printf("\nlist null!\n");
	else
	{
		p1=head;
		while(num!=p1->num&&p1->next!=NULL) 
		//前者保证num是否为我所想删除的num
		//后者遍历整个链表是否能找到(找不到的情况) 
		{
			p2=p1;
			p1=p1->next;
		}
		if(num==p1->num)
		{
			if(p1==head)//如果删除的是第一个头节点 
			{
				head=p1->next;
			}
			else//非头节点 
			{
				p2->next=p1->next;	
				
			}
			printf("\nDelete No:%d succeed!\n",num);
			free(p1);//释放空间 
		} 
		else
			{
			printf("%d not been found!\n",num); //找不到要删除的节点 
			} 
		return(head); 
	}

} ``

你可能感兴趣的:(#,数据结构,#,c,lanuage,#,c++,plus,链表,指针,数据结构)