数据结构基础知识(一)

1> 将今天所敲课堂代码,自己手动实现一遍,并详细注释

2> 绘制思维导图

 知识点一:值传递、地址传递、值返回、地址返回

#include <stdio.h>
//值传递
void swap(int m,int n)
{
	int temp;
	temp=m;
	m=n;
	m=temp;
	printf("m=%d,n=%d\n",m,n);//123  0
}
//值传递
void fun(int *p,int*q)
{
	int *temp;
	temp=p;
	p=q;
	q=temp;
	printf("*q=%d\t*p=%d\n",*q,*p);//123 0
	printf("q=%p\tp=%p\n",q,p);
}
//地址传递
void gun(int *p,int *q)
{
	int temp;
	temp=*p;
	*p=*q;
	*q=temp;	
	printf("*q=%d , *p=%d\n",*q,*p);//123 0
	printf("q=%p , p=%p\n",q,p);
}
//值返回
int hun()
{
	int value=666;
	return value;
}
//地址返回
int *iun()
{
	static int value=666;
	return &value;
}
int main(int argc, const char *argv[])
{
	int num1=123;
	int num2=0;
   //调用swap函数交换两数
	swap(num1,num2);
	printf("swap使用后num1 = %d,num2 = %d\n",num1,num2);//123 0  成功交换
    printf("swap调用后的地址num1=%p,num2=%p\n",&num1,&num2);

	//调用fun函数交换两数
	fun(&num1,&num2);	
	printf("fun使用后num1 = %d,num2 = %d\n",num1,num2);//123 0  成功交换
    printf("fun调用后的地址num1=%p\tnum2=%p\n",&num1,&num2);

	//调用gun函数交换两数
	gun(&num1,&num2);
	printf("gun使用后num1 = %d,num2 = %d\n",num1,num2);	
    printf("guh调用后的地址num1=%p\tnum2=%p\n",&num1,&num2);

	//调用hun函数
	int ret=hun();
	printf("hun()=%d\n",ret);

	//调用iun函数
	int *ret1=iun();
	printf("value=%p\n",ret1);

	return 0;
}

运行结果:

m=123,n=0
swap使用后num1 = 123,num2 = 0
swap调用后的地址num1=0x7ffe66d3b0d4,num2=0x7ffe66d3b0d8

*q=123    *p=0
q=0x7ffe66d3b0d4    p=0x7ffe66d3b0d8
fun使用后num1 = 123,num2 = 0
fun调用后的地址num1=0x7ffe66d3b0d4    num2=0x7ffe66d3b0d8

*q=123 , *p=0
q=0x7ffe66d3b0d8 , p=0x7ffe66d3b0d4
gun使用后num1 = 0,num2 = 123
guh调用后的地址num1=0x7ffe66d3b0d4    num2=0x7ffe66d3b0d8

hun()=666
value=0x55b65da46010

 知识点二:内存分区

一个进程启动后,系统会为该进程分配4G的虚拟内存;3--4G是内核空间,主要与底层驱动打交道0-3G用户空间又被划分为三部分:栈区、堆区、静态区(全局区);全局区又分为四个段:.bss段、.data段、.ro段、.txt段

#include <stdio.h>
#include <stdlib.h>
int m;       //未初始化的全局变量,在全局区的.bss段
int n=0;     //已经初始化的全局变量,在全局区的.data段

static int k;//未初始化的静态变量,在全局区的.bss段
static int l=666;//已经初始化的静态变量,在全局区的.data段

char arr[100]="hello";//arr数组在全局的.data段,hello在全局区的.ro段
char *p="world";//指针在.data段,world 在全局区的.ro段

int main(int argc, const char *argv[])
{

	int m1; //局部变量在栈区申请,初始值为随机值
	int n1=0;//局部变量在栈区申请

	static int k1;//静态局部变量,在全局区的.bss段申请
	static int l1=666;//静态局部变量,在全局区的.data段申请
	char arr1[100]="hello";//q在栈区申请的8字节,但是"hello"在全局区的.ro段
	char *p1="world";//数组在栈区申请,"world"在全局区的.ro段

	int *ptr=(int*)malloc(sizeof(int));//ptr是在栈区,而申请的空间在堆区

	return 0;
}

知识点三:动态内存分配和回收(malloc、free)

C语言中可以使用malloc和free来对堆区空间进行操作

#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char *argv[])
{
	//在堆区申请一个int类型空间大小
	int *p1 = (int *)malloc(4);//申请4字节大小
	printf("*p1=%d\n",*p1);//随机值

	int *p2 = (int *)malloc(sizeof(int));//申请一个int类型空间大小
	*p2 = 520;//给堆区进行赋值
	printf("*p2=%d\n",*p2);
    
	//连续申请5个int类型的大小
	int *p3=(int*)malloc(sizeof(int)*5);
	//输出默认值
	for(int i=0;i<5;i++)
	{
		printf("%d\t",*(p3+i));
	}
	printf("\n");

	//释放堆区空间
	free(p1);
	p1=NULL;//防止野指针
	free(p2);
	p2=NULL;
	free(p3);
	p3=NULL;

		return 0;
}

*p1=0
*p2=520
0    0    0    0    0

练习:要求在堆区申请6个int类型空间存放6名学生的成绩,分别使用函数实现申请空间、输入学生成绩、输出学生成绩、对学生进行升序排序、释放空间

#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char *argv[])
{
	//在堆区申请一个int类型空间大小
	int *p1 = (int *)malloc(4);//申请4字节大小
	printf("*p1=%d\n",*p1);//随机值

	int *p2 = (int *)malloc(sizeof(int));//申请一个int类型空间大小
	*p2 = 520;//给堆区进行赋值
	printf("*p2=%d\n",*p2);
    
	//连续申请5个int类型的大小
	int *p3=(int*)malloc(sizeof(int)*5);
	//输出默认值
	for(int i=0;i<5;i++)
	{
		printf("%d\t",*(p3+i));
	}
	printf("\n");

	//释放堆区空间
	free(p1);
	p1=NULL;//防止野指针
	free(p2);
	p2=NULL;
	free(p3);
	p3=NULL;

		return 0;
}
运行结果:                                                                                                                             申请成功
请输入第0学生成绩
33
请输入第1学生成绩
11
请输入第2学生成绩
100
请输入第3学生成绩
78
请输入第4学生成绩

请输入第5学生成绩
2
成绩录入完毕
排序成功
2    7    11    33    78    100

知识点四:类型重定义

(1)类型重定义与宏定义的区别

1> 宏定义只是单纯的替换,不做任何正确性检测,是一个预处理指令

2> 类型重定义,需要做正确性检测,是一条语句

3> 宏替换发生在预处理阶段,而类型重定义发生在编译阶段

4> 如果是对普通单个重命名没有问题,但是对指针重命名就有问题了

#include <stdio.h>
#define ptr_i int*
typedef int* pptr_i;

int main(int argc, const char *argv[])
{
	ptr_i a,b;   //a是指针类型,b是普通int类型

	pptr_i m,n;  //m和n都是指针类型
	printf("sizeof a=%ld\n",sizeof(a));//8
	printf("sizeof b=%ld\n",sizeof(b));//4

	printf("sizeof m=%ld\n",sizeof(m));//8
	printf("sizeof n=%ld\n",sizeof(n));//8

	return 0;
}
//宏定义与类型重定义区别

 知识点五:结构体

(1)结构体的格式

struct 结构体名

{

成员类型1 成员变量1;

成员类型2 成员变量2;

。。。

成员类型n 成员变量n;

};

注意: 1、struct是定义结构体的关键字

2、结构体名:是一个标识符,要符合标识符的命名规则,一般首字母大写

3、所有的成员属性使用一对花括号包裹,最后用分号结束,分号不能省略

4、成员属性类型可以是基本数据类型,也可以是构造数据类型

5、声明结构体不占内存空间,使用结构体类型定义变量时,变量会占用内存空间

6、一般将声明结构体放在文件头部或者头文件中,也可以声明在其他部分,但是,至少要声明在使用之前

(2)举例 

//声明一个卡牌游戏人物结构体类型
struct Ssp
{
char name[20];//姓名
int Hp;       //血量
char skill[20];   //技能
int kill;     //击杀人数
};

(3)结构体变量的定义及初始化

#include <stdio.h>

//声明一个角色结构类型
struct Figue
{
	char name[20];
	char skill[20];
	int Hp;
	double speed;
};

int main(int argc, const char *argv[])
{
    //定义角色变量
	struct Figue f1={"暗夜英雄","审判,rua~",18000,6};
	struct Figue f2={.skill="蹦蹦炸弹",.Hp=30000};
	return 0;
}

(4)结构体指针访问成员

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//声明一个角色结构类型
struct Figue
{
	char name[20];
	char skill[20];
	int Hp;
	double speed;
};

int main(int argc, const char *argv[])
{
	//使用角色类型定义一个角色变量
	struct Figue f1={"暗夜英雄","审判,rua~",18000,6};
	struct Figue f2={.skill="蹦蹦炸弹",.Hp=30000};

	//输出角色变量f1中的所有内容
	printf("f1.name=%s\n",f1.name);
	printf("f1.skill=%s\n",f1.skill);
	printf("f1.Hp=%d",f1.Hp);
	printf("f1.speed=%lf",f1.speed);
//在堆区申请一个角色类型,完成初始化并输出相应属性
struct Figue *ptr=(struct Figue*)malloc(sizeof(struct Figue));
//给角色名字赋值
strcpy(ptr->name,"伞兵\n");//给姓名赋值
strcpy(ptr->skill,"把头低下\n");//给角色技能赋值
ptr->Hp=20000;
ptr->speed=20;
//输出角色指针指向堆区空间的内容
printf("角色名称为:%s\n",ptr->name);
printf("角色技能为:%s\n",ptr->skill);
printf("角色血条为:%d\n",ptr->Hp);
printf("角色速度为:%lf\n",ptr->speed);
	return 0;
}

运行结果

f1.name=暗夜英雄
f1.skill=审判,rua~
f1.Hp=18000f1.speed=6.000000
角色名称为:伞兵

角色技能为:把头低下

角色血条为:20000
角色速度为:20.000000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值