C语言-9、链表 | 共用体union | typedef

链表

数据两种模式
(1)数组-----连续
(2)链表-----非连续
定义链表:链表是一种数据结构,采用动态分配存储单元的方式。它能够有效的节省存储空间
①节点定义:两部分构成:内容数据部分和下一个节点地址  

//节点的定义方式
struct student{
	int num;
	float score;
	struct student *next;//指向自己的指针,节点类型 
}; 
struct student a, *p;

②动态机制:malloc函数
动态存储分配函数#include<stdlib.h>
malloc()函数
格式:malloc(size)
作用:在内存的动态存储分区中分配一个长度为size个字节的连续空间,函数的返回值为一个分配域起始地址
的指针,若干分配失败则返回NULL  

#include<stdlib.h>

//开辟一个用于存放struct student数据的内存空间,并让p指向该空间
//malloc用之前一定要进行强制类型转换,因为malloc返回的是连续占用空间的首地址一个void *型 
struct student *p = (struct student *)malloc(sizeof(struct student));
/*
    节点的定义
*/
struct node{
	int data;
	struct node *next;
};
//指针p指向的是整个节点而不是节点里面其中的数据域
struct node *p = (struct node *)malloc(sizeof(struct node));

free()函数
格式:free(p);
作用:释放用malloc()分配的内存

③生成链表

#include<iostream>
#include<cstdio>
#include<stdlib.h>

using namespace std;
//链表的建立 
struct node{
	int data;
	struct node *next;
};
int main(){
	struct node *head, *p, *q;
	p = (struct node *)malloc(sizeof(struct node));
	p->data = 10;
	head = p;
	q = (struct node *)malloc(sizeof(struct node));
	q->data = 20; 
	q->next = NULL;
	
	p->next = q;
	
	return 0;
}

④链表的三个操作:查、增、删  

链表的访问

#include<iostream>
#include<cstdio>
#include<stdlib.h>

using namespace std;
//链表的建立 
struct node{
	int data;
	struct node *next;
};
int main(){
	struct node *head, *p, *q,*r;
	int sum = 0; 
	float aver;
	p = (struct node *)malloc(sizeof(struct node));
	p->data = 10;
	head = p;
	q = (struct node *)malloc(sizeof(struct node));
	q->data = 20; 
	
	
	r = (struct node *)malloc(sizeof(struct node));
	r->data = 30; 
	p->next = q;
	q->next = r;
	r->next = NULL;
	//链表的访问 
	while(p != NULL){
		sum += p->data;
		p = p->next;
	}
	
	aver = sum / 3;
	printf("%f",aver);
	return 0;
}     
//预期结果
20.000000

2、链表的删除

/*
    删中间
*/
//删除p节点
//1、找到p节点的前一个节点q
q->next = p-next;
free(p)

//若没有p节点,删除q节点的后面一个节点
q->next = q->next->next;
free(p->next)

/*
    删头节点
*/
head = head->next;

/*
    删尾,假设告诉尾节点的前一个节点是q
*/
p = q->next;
q->next = NULL;
free(p)

3、增加节点

/*
    中间插:要在q节点的后面插一个元素s,不可以交换顺序
*/
//先连后断
s->next = q->next;
q->next = s;
/*
    第一个位置插:插一个元素s
*/
s->next = head;
head = s;

/*
    最后位置(q)插:插一个元素s,下面两步可以交换
*/
q->next = s;
s->next = NULL;

三、共用体类型:
共用体中所有成员共用同一段内存(所有成员的起始地址都是一样的)

union 共用体名
{
    成员列表;
};
//定义了一个名为data的共用体类型,该类型有三个成员i, ch, s 
/*
	先定义类型,在定义变量;union data a1
	定义类型的同时定义变量
	直接定义变量 
*/
union data{
	int i; 
	char ch[10];
	float s;
}a1; //a1是变量
/*由于共用体类型变量的所有成员都共用同一段内存,
所以共用体类型变量所用的变量所占的字节数等于
该共用体的类型中占字节数最多的成员所占的字节数

*/
sizeof(a1) = 10

Note:

(1)成员列表为该共用体的成员,成员定义的方式与普通变量的方式一样
(2)成员列表必须用一对花括号
(3)共用体名可以省略

union的经典例题:

#include<iostream>
#include<cstdio>

using namespace std;

union myun{
	struct {
		int x;
		int y;
		int z;
	}u;
	int k;
}a;
int main(){
	
	a.u.x = 4;
	a.u.y = 5;
	a.u.z = 6;
	a.k = 0;
	printf("%d\n",a.u.x);
	
	return 0;
} 
//预期结果:
0
#include<iostream>
#include<cstdio>

using namespace std;

int main(){
	
	union{
		char i[2];
		int k;
	}r;
	r.i[0] = 2;
	r.i[1] = 0;
	printf("%d\n",r.k); 
	
	return 0;
} 
/*
刚开始博主做的时候一看就是20,但是运行结果是错的,经过仔细思考
发现这道题太考的太好了,我们都知道数组中,下标小的低地址,下标大
大地址,问题来了,整数占两个字节,高位占大地址也就是说r.i[1]放的是2
r.i[1] = 0,难道答案是02,胡扯,0在C语言中是8进制标志

*/
//预期结果
2  

四、typedef
用typedef定义新的类型名
在编程中可以用typedef来定义新的类型名来代替已有的类型名

格式:

//typedef 已有类型名 新的类型名
//如:
typedef int INTEGER;
INTEGER a[10], b;
int a[10], b;

                                       typedef 已有类型名 新的类型名
(1)typedef可用于定义各种类型名,但不能定义变量,即只要见到typedef则该语句最后的标识符
一定是个类型名而不是变量名
(2)typedef只能对已近存在的类型新增一个别名,而不是创造新类型,即在typedef后必须是一个已有的类型。

typedef int ARR[10]
ARR a, b[2];//int a[10], b[2][10];

typedef char *POINT
POINT p1, *p2;//char *p1, **p2

版权声明:本文为weixin_42133768原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。