接上次的结构体之后,本篇记录C语言的tydef用法。链表的知识。
都属于较为重要的部分,学习中须多加理解。
链表:
动态内存:
malloc/free
void *malloc(size_t num)
void free(void *P)
int *array = malloc(10 * sizeof(int)); // 分配一个容纳10个int的数组
注意点 :malloc函数并不识别要申请的内存是什么类型的,他只关心内存的字节数。
malloc申请到的是一块连续的内存,有时申请到的大,申请不到的时候会返回null。
malloc的类型是void,在调用时要进行显示转化。转换成所需的类型,
free的参数是 null的话,没有任何效果。
释放内存的一部分是不被允许的。
malloc与free配套使用,注意野指针非常危险。
链表是一种常见的数据结构后,是动态的进行储存分配的一种结构,
组成由头指针和节点组成。
链表结构的定义:
typedef struct Node {
int data ;
struct Node *next;
}Node;
写一个简单的链表在这里作为记录:
#include <stdio.h>
#include <stdlib.h>
struct student {
long num;
float score;
struct student *next;
};
int main()
{
struct student a,b,c,*head;
a.num = 2001;
a.score = 99 ;
b.num = 2002;
b.score = 91;
c.num = 2009;
c.score = 88;
head = &a;
a.next= &b;
b.next = &c;
c.next = NULL;
do{
printf("%ld %5.1f \n", head->num,head->score );
head = head->next;
}while(head != NULL);
return 0;
}
结果:
链表可以分为 单链表,双链表,循环链表。
链表的特点
- 动态大小:链表的大小可以在运行时动态变化。
- 无需连续内存:链表的节点可以在内存中分散存储,不需要像数组那样连续。
- 插入和删除效率高:可以在 O(1) 时间复杂度内完成,只要提供了适当的指针或引用。
下面记录一个关于动态链表的
题目:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define LEN sizeof(struct student) //student的结构体长度
struct student *creat(); //链表创建函数。
void print(struct student *haed); //打印函数,
struct student {
int num;
float score;
struct student *next;
};
int n ; //全局变量,存放记录的节点数。
struct student *creat()
{
struct student *head;
struct student *p1,*p2;
p1 = p2 = (struct student *)malloc(LEN);
printf("please input your num :");
scanf("%d", &p1->num );
printf("please input your score:");
scanf("%f", &p1->score);
head = NULL;
n = 0;
while (p1 ->num)
{
n++;
if(n == 1 )
{
head = p1;
}
else
{
p2 ->next = p1;
}
p2 = p1;
p1 = (struct student *)malloc(LEN);
printf("please input next your num :");
scanf("%d", &p1->num );
printf("please input next your score:");
scanf("%f", &p1->score);
}
p2 ->next = NULL;
return head;
}
void print(struct student *head)
{
struct student *p;
printf("There are have %d record student\n", n);
p = head;
if(head != NULL){
do {
printf("num is %d ,score is %f",p->num,p->score);
p = p->next;
printf("\n");
}while(p);
}
}
int main()
{
struct student *stu;
stu = creat();
print(stu);
printf(" \n");
return 0 ;
}
结果验证:
删除一个节点:
从动态链表删除一个节点,并不是从内存中 ,把他抹掉,而是把他从链表分离开,撤销掉原来的连接关系即可。
当然要进行内存节点的释放,否则会发生内存泄漏的情况。
链表插入节点:
无论是插入还是删除节点,
需要注意的都是创建节点,更新节点的指针,注意顺序的正确,以及头尾节点的情况,具体程序将在之后记录
typedef的用法:
声明新的类型名代替已有的类型名,
#include <stdio.h>
typedef int INTEGER;
int main()
{
INTEGER i = 1;
int j = 2;
printf("%d %d ", i , j );
}
还可以为结构体类型创建别名。 (类似的联合体union,枚举类型enum)
typedef struct
{
int x;
int y;
} Point;
Point p; // 使用别名声明结构体变量
还有指针类型 别名, 结合类型限定符, 数组类型别名。
当不同源文件中用到同一数据类型时,常用typedef声明一些数据类型,把他们单独放在一个文件中,然后在需要用到的文件中用#include把他们包含进来。
有利于程序的通用与移植。
#define和typedef的区别:
#define是在预编译的时候处理的,只能做简单的字符串替换,
而typedef是在编译时候处理的,实际上他并不是简单的字符替换,而是采用如同定义变量的方法那样来声明一个类型。
记录到typedef,下次记录位运算。