结构体+内存空间划分

day1:

day2:

内存空间空间划分,动态申请空间malloc free

typedef,结构体[普通结构体,结构体数组,结构体指针]

共用体

day3:顺序表【增删改查】

day4:

day5:链表:单向链表,单向循环,双向链表,双向循环链表【没有上限】

day6 :栈【增删】,队列【增删】,哈希查找,折半查找

day7:排序算法:交换排序(快速排序),选择排序(简单选择排序,堆排序),插入排序(直接插入排序,希尔排序),归并排序(二路归并,多路归并),基数排序

二叉树【创建,遍历】

数据结构补习

一,内存空间划分

内核

用户空间:

        栈区:由计算机分配空间,计算自动释放空间

                    栈区:需要满足栈的特点,先进后出,后进先出

        堆区:由程序员手动申请空间,手动释放空间    malloc  free

                     堆区:满足队列的特点,先进先出,后进后出(先定义变量,先分配空间)

栈区和堆区没有明确的分界点,直到栈区和堆区的地址重合

        静态区:存储全局变量和静态变量   

                                .bss:存储未初始化的静态变量或全局变量

                                .data:存储已经初始化的静态变量或全局变量

                                 .ro:存储常量,字符串常量,const修饰的全局变量

                                 .txt 文本段,存储二进制文件

二,动态申请和释放空间

动态申请:

头文件:#include<stdlib.h>

格式:void *malloc(size_t size);

返回值:当在堆区申请失败默认返回NULL;如果申请成功,默认返回堆区空间首地址

注意在使用时必须保存堆区的首地址,方便后期空间释放,否则会造成空间泄露问题。

参数:size_t size         size_t: unsigened int

           申请空间大小字节

           使用格式:

                1.单个分配空间

                int *p=(int *)malloc(sizeof(int));

                 注意:p和q只是一个简单的指针,不可以偏移

                  2.多个空间申请

                  int *p=(int *)malloc(sizeof(int)*5);

                   注意:当申请多个空间时,就可以指针偏移

动态释放:

头文件:#include<stdlib.h>

格式:void free(void *ptr);

返回值:无返回值函数

参数:void *ptr;需要释放空间的指针

使用格式:

                free(p);//释放:堆区的空间不被p指向,但是空间还在

                p=NULL;//防止p为野指针

野指针:

1.直接使用未初始化的指针

2.指针指向数组,通过指针越界访问

3.当遇到指针函数返回局部变量的地址

        int *fun()

        {

                int arr[3];

                return arr;//因为arr是局部变量,调用函数分配空间 函数调用结束 函数调用结点空间释放,当返回地址时,就是野指针

                }

4.指向堆区的空间,释放空间以后,就是野指针

free(p)

//主函数.c  写主函数
#include "3.h"
int main(int argc,const char *argv[])
{  
	int n;
	puts("请输入想输入的数字个数:");
	scanf("%d",&n);
	char *str=create_str(n);
	char *str1=create_str(n);
	puts("str:");
	scanf("%s",str);
	puts("str1:");

	scanf("%s",str1);
	printf("%d\n",Mystrcmp(str,str1));
    str=Free_space(str);
	str1=Free_space(str1);
	return 0;
}
//.c文件 写自定义函数
#include "3.h"
char *create_str(int n)
{
	char *p=(char *)malloc(sizeof(char)*n);
	if(p==NULL)
	{
		return NULL;
	}
	return p;
}
int Mystrcmp(const char *p,const char *q)
{
	while(*p&&*p==*q)
	{
		p++;
		q++;
	}
	return *p-*q;
}
char *Free_space(char *p)
{
	if(p==NULL)
		return NULL;
	free(p);
	p==NULL;
	return p;
}

//.h文件 声明函数 声明头文件

#ifndef N
#define N
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *create_str(int n);
int Mystrcmp(const char *p,const char *q);
char *Free_space(char *p);
#endif

三,类型重定义typedef

作用:起别名,起小名

格式:typedef  数据类型 别名;

        数据类型:基本类型 构造类型 指针 空类型

        别名:满足命名规范,可以是多个

        int a=10;#

3.1类型推导

3.2 宏和类型重定义的区别

typedef int size_4    等价  #define size_4 int 

1>宏只属于宏替换,类型重定义属于类型重定义

2>宏不属于C语句,类型重定义属于C语句

3>宏在预处理阶段,类型重定义在编译阶段

4>宏只可以做简单类型的替换,但是类型重定义可以重定义任意一种类型

四,结构体struct

结构体:用来存储多个相同或不同类型元素的构造数据类型

构造类型:可以拆分

        int arr[3]={1,2,3}

定义格式: struct 结构体名

                   {

                        数据类型 成员1;

                        数据类型 成员2;

                        ...

                        数据类型  成员n;

                                        };

1.struct:结构体的关键字

2.结构体名:满足命名规范 可有可无

3.{  }不可省略

4.数据类型:基本类型 构造类型 指针 空

5.成员变量的个数任意

6.结构体后面的分号必须存在

7.结构体的描述位置任意,一般在全局

8,结构体描述 计算机不分空间 直到定义结构体变量才分配

4.1结构体普通变量

直接定义(可省略结构体名)/间接定义(不可省略结构体名)

1.按顺序初始化

2.不按顺序初始化

3.定义结构体变量

4.结构体输入输出

//四种初始化结构体变量的方式 stu1 stu2 stu3 stu4
#include <stdio.h>
#include<string.h>
//结构体在引用成员时,必须使用结构体变量加“.”区进行调用
struct student
{
	char name[20];
	int age;
	float score;
	char sex;
}stu1={"金一",12,100,'m'},
	stu2={.age=11,.name="二金"},
	stu3,stu4;
void output(struct student stu)
{
	printf("name=%s,age= %d,score=%f,sex= %c\n",stu.name,stu.age,stu.score,stu.sex);
}

int main(int argc,const char *argv[])
{  
	strcpy(stu3.name,"三金");
	stu3.age=22;
	stu3.score=99;
	stu3.sex='w';
	puts("请输入姓名 年纪 成绩 性别:");
	scanf("%s",stu4.name);
	scanf("%d",&stu4.age);
	scanf("%f",&stu4.score);
	scanf(" %c",&stu4.sex);
	output(stu1);
	output(stu2);
	output(stu3);
	output(stu4);
	return 0;
}

4.2结构体数组

4.2.1定义结构体同时定义变量,并初始化

struct student
{
    char name[20];
    int age;
    float score;
    char sex;
}arr1[2]={"金一",12,100,'m',"金二",13,91,‘m'’},【多使用】

arr2[2]={{"金一",12,100,'m'},{"金二",13,91,‘m’}},

arr3[2]={[0]={"金一",12,100,'m'},[1]={"金二",13,91,‘m’}},

arr4[2]={[0]={.name="金一",.age12},[1]={age=12}},//不按顺序初始化

struct student
{
    char name[20];
    int age;
    float score;
    char sex;

}arr[2];

arr[0]//表示第一个人所有信息

arr[0].name//表示第一个人的姓名

arr[1].sex//表示第二个人的性别

strcpy(arr[0].name,"李四")

结构体数组循环输入输出

struct student
{
    char name[20];
    int age;
    float score;
    char sex;

}arr[2];

for(int i=0;i<2;i++)

{

  scanf("%s",arr[i].name);

  scanf("%d",&arr[i].age);

  scanf("%f",&arr[i].score);

 scanf(" %c",&arr[i].sex);

}

#include <stdio.h>
#include<string.h>
struct student
{
	char name[20];
	int age;
	float score;
	char sex;
};
void output(struct student stu[])
{
	int i;
	for(i=0;i<2;i++)
	printf("name=%s,age= %d,score=%f,sex= %c\n",stu[i].name,stu[i].age,stu[i].score,stu[i].sex);
}

int main(int argc,const char *argv[])
{  
	struct student stu1[2]={[0]={"金一",12,100,'m'},[1]={.age=11,.name="二金"}},
	stu2[2]={"金三",11,91,'w',"金四",12,100,'m'},
	stu3[2],stu4[2];
	strcpy(stu3[0].name,"5金");
	stu3[0].age=23;
	stu3[0].score=88;
	stu3[0].sex='w';	
	strcpy(stu3[1].name,"6金");
	stu3[1].age=24;
	stu3[1].score=89;
	stu3[1].sex='w';
	puts("请输入姓名 年纪 成绩 性别:");
 

	int i;
	for(i=0;i<2;i++)
	{
		scanf("%s",stu4[i].name);
		scanf("%d",&stu4[i].age);
		scanf("%f",&stu4[i].score);
		scanf(" %c",&stu4[i].sex);

	}
	output(stu1);
	output(stu2);
	output(stu3);
	output(stu4);
	return 0;
}

4.2.2定义结构体后定义变量,并初始化

#include <stdio.h>
#include<string.h>
struct car
{
	char brand[20];
	int price;
	char color;
};
void input(struct car str[])
{
	int i;
	for(i=0;i<5;i++)
	{
		puts("请输入 牌子 价格 颜色:");
		scanf("%s",str[i].brand);
		scanf("%d",&str[i].price);
		scanf(" %c",&str[i].color);

	}
}

void output(struct car str[])
{
	int i;
	for(i=0;i<5;i++)
	printf("brand=%s,price= %d,color= %c\n",str[i].brand,str[i].price,str[i].color);
}
void maxprice(struct car str[])
{
	int max=0;
	int i;
	for(i=1;i<5;i++)
	{
		if(str[i].price>str[max].price)
			max=i;
	}
	printf("最贵的品牌和车子价格为:%s,%d元\n",str[max].brand,str[max].price);
}
void maopao(struct car str[])
{
	int i,j;
	struct car temp;
	for(i=0;i<4;i++)
	{
		for(j=0;j<4-i;j++)
			if(str[j].price>str[j+1].price)
			{
			temp=str[j];
			str[j]=str[j+1];
			str[j+1]=temp;
			}


	}
}
int main(int argc,const char *argv[])
{  
	struct car str[5];
	input(str);
	maxprice(str);
	maopao(str);
	output(str);
	return 0;
}

4.3 结构体指针

结构体指针使用->调用

地址使用->  值使用.

struct student
{
    char name[20];
    int age;
    float score;
    char sex;

}*p;//直接定义

struct student *p;//间接定义

2>指针的使用

2.1 结构体指针指向普通变量的地址

struct student stu={"张三",14,100,‘w'};

struct student *p=&stu;

p->name等价于 stu.name;表示名字((*p).name   &stu->name)

p->sex 等价于stu.sex:表示性别

#include <stdio.h>
struct student
{
	char name[20];
	int age;
	float score;
	char sex;
};
int main(int argc,const char *argv[])
{  
	struct student stu={"张三",14,100,'W'};
	struct student *p=&stu;
	//地址使用->,应用成员变量
	//值使用.应用成员变量
	printf("%s %d %.2f %c\n",p->name,p->age,p->score,p->sex);
	printf("%s %d %.2f %c\n",stu.name,stu.age,stu.score,stu.sex);
	printf("%s %d %.2f %c\n",(*p).name,p->age,p->score,p->sex);
	return 0;
}

2.2 结构体指针指向结构体数组的首地址

         struct student stu[2]={“李四“,12,98,'m',"小王",15,100,'w'};

          struct student *p=stu;

        for(int i=0;i<2;i++)

        {

        printf("%s %d %f %c",(p+i)->name,(p+i)->age,(p+i)->score,p->sex);

        }

2.3 结构体指针指向堆区的空间【重点】

int *p=(int *)malloc(sizeof(int));

//结构体指针指向单个的结构体空间

struct student *p=(struct student *)malloc(sizeof(struct student));

//结构体指针指向连续的结构体空间

struct student *p=(struct student *)malloc(sizeof(struct student)*5);

查找一个字符串相同结构体成员,并输出

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student
{
	char name[20];
	int age;
	float score;
	char sex;
};
struct student *create(int n)
{
	struct student *p=(struct student *)malloc(sizeof(struct student)*n);
	if(p==NULL)
		return NULL;
	return p;
}
void input(struct student *p,int n)
{
	int i;
	for(i=0;i<n;i++)
	{
		puts("name:");
		scanf("%s",(p+i)->name);
		puts("age:");
		scanf("%d",&(p+i)->age);
		puts("score:");
		scanf("%f",&(p+i)->score);
		puts("sex:");
		scanf(" %c",&(p+i)->sex);
	}
}
void output(struct student *p,int n)
{
	int i;
	for(i=0;i<n;i++)
	{
		printf("%s\t%d\t%.2f\t%c\n",(p+i)->name,(p+i)->age,(p+i)->score,(p+i)->sex);
		}
}
int serc(struct student *p,int n)
{
	int i;
	char str[20];
	puts("请输入你想找的名字:");
	scanf("%s",str);
	for(i=0;i<n;i++)
	if(strcmp((p+i)->name,str)==0)
	{
		return i; 
	}

	return -1;
}
int main(int argc,const char *argv[])
{  
	struct student *p=create(5);
	input(p,5);
	output(p,5);
    int i=serc(p,5);
	if(i==-1)
	{
		printf("错误,没找到\n");
	}
  else
	  printf("你想找的学生信息:%s\t%d\t%.2f\t%c\n",(p+i)->name,(p+i)->age,(p+i)->score,(p+i)->sex);
}

4.4 结构体引用

1>普通结构体变量时使用. 引用

2>结构体数组需要结构体数组名加.引用

3>结构体指针,需要使用“->”引用

4>结构体变量不可以整体输出,常用来实现交换,或者做参数实现传递

4.5 typedef和结构体结合

typedef struct student

{

        char name[20];

        int age;

}stu,stu_arr[3],*stu_p;

stu a;

stu arr[3] --->stu [3]

stu *p

4.6普通结构体嵌套

//定义一个人:姓名,年龄,出生年月日

typedef struct Birth

{

        int year;

        int month;

        int day;

}bir;

typedef struct person

{

        char name[10];

        int age;

        bir birth;

}per;

per a;-->struct person a;

4.7结构体嵌套结构体数组

typedef struct //结构体名可以不写

{

        char name[10];

        int price;

        char color[20];

}car;

typedef struct person

{

        char name[10];

        int age;,

        car arr[3];

}per;

per a={"张三',14,“大众”,111111,“黑色”,“宝马”,222222,“黄色”,“奔驰,333333,“绿色”}

打印大众 a.arr[0].name

typedef struct 
{
	char name[10];
	int price;
	char color[10];
	
}car;
typedef struct student
{
	char name[20];
	int age;
	float score;
	char sex;
	car c[3];
	
}*stu_p,stu_t;
int main(int argc,const char *argv[])
{ 
	int i;
	stu_t a={"张三",12,100,'m',"DZ",10000,"YELLOW","BC",12222,"BLUE","BYD",11111,"BLACK"};
	for(i=0;i<3;i++)
	{
		printf("%s\t%d\t%s\n",a.c[i].name,a.c[i].price,a.c[i].color);
	}
}

4.8 结构体存储空间【重点】

64位操作系统

1>结构体变量的地址是结构体第一个成员的首地址

2>结构体每个成员的地址是连续的

3>结构体的大小等于各个成员的总和

4>满足字节对齐原则:

        1.结构体的总字节数是最宽成员的整数倍,否则使用空字节填充

        2.结构体的首地址是最宽成员的整数倍

        3.结构体各个成员的偏移量是该成员字节大小的倍数,否则使用空字节填充

偏移量:该成员的地址编号到起始地址之间的差

        如果成员是char,则偏移量是1的倍数

        如果成员short,则偏移量是2的倍数

        如果成员是 int float 则偏移量是4的倍数

        如果成员是double long 指针则偏移量是8的倍数

32位操作系统

满足字节对齐原则:

1>结构体变量的地址是结构体第一个成员的首地址

2>结构体每个成员的地址是连续的

3>结构体的大小等于各个成员的总和

4>满足字节对齐原则:

        1.结构体的总字节数是最宽成员的整数倍,否则使用空字节填充

        2.结构体的首地址是最宽成员的整数倍

        3.结构体各个成员的偏移量是该成员字节大小的倍数,否则使用空字节填充

偏移量:该成员的地址编号到起始地址之间的差

        如果成员是char,则偏移量是1的倍数

        如果成员short,则偏移量是2的倍数

        如果成员是 int float double long 指针则偏移量是4的倍数

4.9 共用体union

共用体:存储类型相同或不同的构造类型

特点:成员共用一片空间

1>共用体的各个成员占用同一片空间

2>共用空间

4.9.1共用体定义和初始化

1>直接和间接定义和初始化

union

{

        int a;

        char c;

        float b;

}value;

4.9.2结构体和共用体结合

1>共用体在结构体外嵌套

2>共用体在结构体内嵌套

#include <stdio.h>
/*typedef union
{
	float score;
	char postion[20];
}u;*/
typedef struct
{
	char name[20];
	char sex;
	char job;
union
{
	float score;
	char postion[20]
};
}a;
int main(int argc,const char *argv[])
{  
//	a value1={"金日成",'M','s',.value.score=100};
	a value1={"金小城",'M','T',.postion="数学老师"};

	printf("%s\t%c\t%c\t%s\n",value1.name,value1.sex,value1.job,value1.postion);
	return 0;
}

 

#include <stdio.h>
#include <stdlib.h>
typedef struct
{
	char name[20];
	char sex;
	char job;
	union
	{
		float score;
		char postion[20]
	};
}a,*p,per[5];
p create(int n)
{
	p q=(p)malloc(sizeof(a)*n);
	if(q==NULL)
		return NULL;
	return q;

}
void input(p q,int n)
{
	int i;
	for(i=0;i<n;i++)
	{

			puts("请输入姓名:");
		scanf("%s",(q+i)->name);
			puts("请输入性别:");
		scanf(" %c",&((q+i)->sex));
			puts("请输入身份:");
		scanf(" %c",&((q+i)->job));
		if((q+i)->job=='t')
		{	puts("请输入职位:");
		scanf("%s",(q+i)->postion);}
		else{
			puts("请输入成绩:");
		scanf("%f",&((q+i)->score));
		}
	}
}
void output(p q,int n)
{
	int i;
	for(i=0;i<n;i++)
		if((q+i)->job=='t')
		printf("%s\t%c\t%c\t%s\n",(q+i)->name,(q+i)->sex,(q+i)->job,(q+i)->postion);
	else
		printf("%s\t%c\t%c\t%.2f\n",(q+i)->name,(q+i)->sex,(q+i)->job,(q+i)->score);

}
void average(p q,int n)
{
	int i,count=0;
	float sum=0;
	for(i=0;i<n;i++)
		if((q+i)->job=='s')
		{
			sum+=(q+i)->score;
			count++;
		}
	printf("average=%.2f\n",sum/count);
	}
void number(p q,int n)
{
	int i,count=0;
	for(i=0;i<n;i++)
		if((q+i)->job=='t')
			count++;
	
	printf("老师个数=%d\n",count);
	}

int main(int argc,const char *argv[])
{  
	p arr=create(5);
	input(arr,5);
	output(arr,5);
	average(arr,5);
	number(arr,5);
	free(arr);
	arr=NULL;
		return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值