结构体
任意由程序员定义出来的新类型
Struct student(Google编程规范)结构体的名字首字母大写
int i;是抽象与具体的关系;int是抽象的,i是具体的
类比认识:
框起来的部分是类型名,i和s是变量名
将结构体的变量名删掉,那么后续使用者就不能再定义变量,因为已经定义好了s1,s2
结构体的初始化和赋值
部分初始化,剩下未初始化的部分是0,是.score,成员初始化与初始化之间用,隔开。
结构体对齐:浪费几个字节,提高程序运行效率
结构体对齐规则:
1、结构体按照其最长成员大小对齐,意味着最终的大小必须是最长成员大小的整数倍;
2、结构体成员按照结构体成员声明先后次序依次存放,并且每个成员的首字节放置的位置必须能够整除成员的字节数;
从小到大依次定义,占的字节空间是最少的
3、如果结构体某个成员的字节数大于CPU的字节数,则最长按照CPU的字节数对齐;(64位为8,32位为4)
4、用预处理命令#pragma pack(n) 可以强制编译器按照指定的n来对齐,合法的n的数值分别是1、2、4、8、16。
结构体传参
结构体亦可以通过指针进行传参,通过指针传参只需要8个字节,而如果通过值传递需要原有结构体那么大的空间,指针传参效率更高
结构体数组
结构体是可以整体赋值
链表
链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。链表是由若干节点node组成的。
形式:
前一个节点的指针域指向下一个节点的值域
Phead:头指针
优势:
对于链表而言,删除和插入的算法复杂度均为1
节点都是从堆上来的
各个节点都是主程序在不同时间malloc申请来的,所以前一个节点和后一个节点的地址不连续,那么就不能用phead+1去查找下一个,只能一个一个挨个去捋一遍
区分有头链表和无头链表:第一个节点是否有效
有头链表:
第一个黄色结点值起到一个领头作用,其值我们并不关心,称为首节点
首节点的下一个节点称为头节点,是指针开始需要的节点
首节点在栈上,头节点在堆上
练习:
编写程序实现链表的头插、遍历、计算有效节点个数和判空
struct Node
{
int data;
struct Node *next;
};
void push_front(struct Node *pHead,int n)
{
struct Node *pNew = malloc(sizeof(struct Node));
pNew->next = pHead->next;
pHead->next = pNew;
pNew->data = n;
}
int printList(struct Node *pHead)
{
struct Node *p = pHead->next;
int counter = 0;
while(p != NULL)
{
printf("%d\n",p->data);
p = p->next;
++counter;
}
return counter;
}
int isEmpty(struct Node *pHead)
{
return pHead->next == NULL;
}
int main()
{
struct Node head = {0,NULL};
push_front(&head,1);
push_front(&head,2);
push_front(&head,3);
push_front(&head,4);
printList(&head);
return 0;
}