结构体(学习郝斌老师课程)
一、为什么需要结构体
为了表示一些复杂的事物,普通的基本类型无法满足实际需要。
二、什么是结构体
为了模拟一些复杂的事物,把一些基本的数据类型组合在一起,形成了一种新的复合数据类型。
三、如何定义结构体(3种方式)
//第一种:经常使用,也是推荐的一种。
struct student1
{
int age;
floate score;
char sex;
};
//第二种
struct student2
{
int age;
floate score;
char sex;
}st2;
//第三种
struct
{
int age;
floate score;
char sex;
}st3;
四、结构体使用
4.1、赋值和初始化
int main(void)
{
struct student1 st1 = {30, 66.6, 'm'}; //方法一:初始化,定义的同时赋值
struct student1 st2; //方法二:先定义结构体变量,然后结构体成员一个一个赋值。
st2.age = 10;
st2.sex = 'w';
return 0;
}
4.2、如何取出结构体变量成员
4.2.1、结构体变量名.成员变量名
4.2.2、结构体指针变量名->成员变量名
int main(void)
{
struct student1 st1 = {30, 66.6, 'm'}; //方法一:初始化,定义的同时赋值
struct student1 *pst = &st1;
printf("%d\n", pst->age); //pst->age在计算机内部会被转化成(*pst).age。这就是->的含 义,是一种规定。
//pst->age的含义:指pst所指向的结构体变量中age这个成员。
return 0;
}
4.3、结构体变量和结构体指针变量作为函数参数传递的问题
//第一种:经常使用,也是推荐的一种。
struct student1
{
int age;
floate score;
char sex;
};
void InputStudent(struct student1 *pstu) //使用指针好处:1、InputStudent程序在分配空间 时只分配了4个字节空间大小。
{ //2、函数内部直接对指针所指的变量本身进行操作。
pstu->age = 10;
pstu->score = 88.8f;
pstu->sex = 'f';
}
int main(void)
{
struct student1 st;
InputStudent(&st);
return 0;
}
//指针的优点
1、耗用内存小。
2、执行速度快
3、快速传递数据
4.5、结构体变量的运算
结构体变量不能进行加减乘除运算,但可以相互赋值。
int main(void)
{
struct student1 st1;
struct student1 st2 = {30, 66.6, 'm'};;
st1 = st2;
return 0;
}
4.6、链表
我们至少可以通过2种结构来存储数据
4.6.1、数组
缺点:
1、当需要存储一个比较大的数据时,如果使用数组,就意味着需要计算机分配一个连续的一整块内存空间系统会分配空间失败。
2、因为数组的连续性,导致数组插入和去除非常困难。
优点:操作简单,存取速度快。
4.6.2、链表
优点:
1、插入删除效率高。
2、不需要连续的内存空间。
缺点:
1、查找时需要从头遍历。数组可以通过下标来快速找到。
4.6.3、链表的专业术语
首节点:存放第一个有效数据的节点。
尾节点:存放最后一个有效数据的节点。
头结点:
头结点的数据类型和首节点的类型是一摸一样
头结点是首节点前面哪个节点
头结点并不存放有效数据
设置头结点的目的是为了方便对链表操作
头指针:存放头结点地址的指针变量。
确定一个链表只需要一个参数即头指针
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct Node
{
int data;
struct Node *pNext;
};
struct Node *CreatList(void)
{
int len;
int i;
int val;
//创建头结点并返回头指针
struct Node * pHead = (struct Node *)malloc(sizeof(struct Node));
if(NULL == pHead)
{
printf("分配空间失败!\n");
return;
}
struct Node *pTail = pHead; //操作指针保存头结点地址
pTail->pNext = NULL;
printf("输入需要生成量表的结点数:len = ");
scanf("%d", &len);
for(i=0; i < len; i++)
{
printf("输入第%d个节点的值:", i+1);
scanf("%d", &val);
struct Node *pNew = (struct Node *)malloc(sizeof(struct Node));
if(NULL == pNew)
{
printf("分配空间失败!\n");
return;
}
pNew->data = val;
pNew->pNext = NULL;
pTail->pNext = pNew; //把新节点保存在操作指针所指向结构体变量的地址域内
pTail = pNew; //移动操作指针,每次都指向最新创建的节点上(即尾节点)。
}
return pHead;
}
void traverse_list(struct Node *pHead)
{
struct Node *p = pHead;
while(NULL != p)
{
printf("%d \n", p->data);
p = p->pNext;
}
printf("\n");
return;
}
int main(void)
{
struct Node *pHead = NULL; //pHead(头指针)用于存放链表头结点的地址。
pHead = CreatList(); //创建链表时一定是动态造节点(因为CreatList函数运行结束后分配空间不能够被释放)
traverse_list(pHead);
return 0;
}