数据结构的C语言基础
1. 数据输出
printf()
函数为格式输出函数,它存在于标准函数库中,在C语言程序中可以直接调用,但程序源文件的开头必须包含以下命令:#include < stdio.h >
或#include "stdio.h "
%-md
:数据以左对齐占m列形式输出,数位不足时从右侧补充空格。.(小数点):用于分隔域宽与输出精度,通常与输出宽度和数据精度结合使用。
2. 一维数组
- 对一维数组的初始化有两种方式:一种是在数组定义时进行初始化,另一种是先定义数组,然后再对数组元素进行一一赋值。
- 定义时初始化定义数组时进行初始化的具体形式为:
类型说明符 数组名[ 常量表达式]={ 表达式1 ,表达式2 ,…表达式n}; 
先定义,再赋值的情况下,数组就无法再用大括号进行整体赋值了。此时,我们就需要对数组元素进行一一赋值。
3.指针基础
- 定义时初始化定义数组时进行初始化的具体形式为:
- 指针是一种数据类型,计算机内存地址所存储的数据内容的类型就是指针的类型,因此不同类型变量的地址具有不同的指针类型。
- 取地址运算符__"&"__只能作用于变量,包括基本类型的变量、数组元素、结构体变量等,不能作用于数组名、常量或寄存器变量等。在C语言中,数组名是数组的首地址,是一个地址常量。
- 相同类型的指针可以进行减运算,运算的结果表示这两个指针所指地址之间的元素个数,而不是相差的字节数。
- 假设p和q是指向同一数组的元素的指针,指针变量p所指元素位于指针变量q所指元素之前,则: p>q结果为0
- 指针变量的赋值是将一个对象的地址赋值给一个指针变量,这个地址是__系统分配的地址__而不是用户自己想定的数值,对象的地址可以是一般的地址常量或地址变量。
- 若要对不同基本类型的指针赋值时,必须使用强制类型转换。
- 任何类型的指针都可以直接赋给void指针,void指针也可以直接赋给任何类型的指针变量。
- void用于说明函数返回值类型时表示函数无返回值,用于说明函数参数时表示函数无参数。
- void*是一种通用指针类型,当void用于说明指针时表示该指针指向不定类型,void指针可以指向任何类型。但void指针和其他任何类型的指针之间不能作加减运算。
- 当指针变量暂时不用时可以赋空值,也就是将指针初始化为0。C语言中习惯用符号常量NULL表示空指针。
#define NULL 0
void指针和NULL指针可以与任何类型的指针比较。NULL指针与其他类型的指针之间通常运用"=="和"!="关系运算符。
4.指针进阶
- C语言为二维数组设置了两种不同类型的指针变量:一种是直接指向二维数组元素的指针变量,另一种是指向二维数组行的指针变量。
- (1)二维数组的首地址为:
a,a[0],&a[0][0]
(2)二维数组第i行的首地址为:a[i],*(a+i)
(3)二维数组第i行第j列元素的地址为:&a[i][i],a[i]+j,*(a+i)+j,a+i*h+j(h表示每行的元素个数)
(4)二维数组第i行第j列元素a[i][i],*(a[i]+j),*(*(a+i)+j),*(a+i*h+j)(h表示每行的元素个数
- 定义字符数组以后只能对其进行逐个元素进行赋值,不能整体赋值。可以使用输入语句对其进行赋值
- 虽然数组名表示数组的首地址,但它是一个常量不能对其进行赋值。
- (1)二维数组的首地址为:
- ==指针数组==的定义形式为:
数据类型 *数组名[数组长度];
数组名[数组长度]结合以后再与""结合,类似于指针变量的定义。这是由于"[]"的优先级高于""运算符。上例中,p[4]表示数组,再与"*"结合,表示该数组为指针类型,即数组元素的值是地址。- int (p)[10]; 表示定义了一个指向数组的指针,这个数组具有10个整型元素。也就是说指针变量p是一个指向10个整型元素的数组的指针。 int p[10]; 定义了一维数组p,它含有10个元素,每一个元素都是指针,是指向整型变量的指针。
- 用指针数组表示二维数组在效果上与数组的下标表示是相同的,只是表示形式不同,但是用指针方式存取数组元素比用下标速度快,而且每个指针所指向的数组元素个数可以不同。
- 指针数组在对字符串进行操作时与字符串数组表达的效果相同。例如:
char *alpha[4] ={"she","is","a","girl"}; char alpha[][80]= {"she","is","a","girl"};
- 指针数组在定义的时候不需要说明每个字符串的长度,只需要说明指向字符串的指针个数,而字符串数组必须说明每个字符串的长度,而且每个字符串定义的长度相同。
- 指针数组在对字符串进行操作时与字符串数组表达的效果相同。例如:
- 任何变量在内存中都对应一定的内存单元,指针变量在内存中也有地址,用于存放指针变量地址的指针变量称为指向指针的指针或二级指针。二级指针变量是一种间接指向目标的指针变量。二级指针的一般定义形式为:
数据类型 **指针变量名;
- 二级指针指向的是指针变量的地址,二级指针不能直接指向数据对象,因此二级指针必须与一级指针配合使用才有意义。
- 函数的起始地址通常作为函数的入口地址,函数名代表着函数的入口地址,在程序编译时,将函数名转换为入口地址,程序找到函数的入口地址也就找到了函数。因此可以定义指针变量指向函数的入口地址,也就是说通过指针变量来调用函数,==我们称这个指针变量为指向函数的指针,即函数的指针。==
- 指向函数的指针变量定义的格式为:
数据类型 (*指针变量名)(函数参数列表)
- 定义的函数指针变量的类型必须与所指向的函数的返回值类型一致,否则不能指向该函数
- 在此定义的是指向函数的指针,因此"*指针变量名"必须用括号括起来
- 定义函数指针的同时为其赋值。一般形式为:
数据类型 函数声明,(*指针变量名)()=函数名;
- 利用函数指针调用函数的两种方式效果是相同的,根据个人需要选择使用。
x=p(a,b);
这种调用方式是将函数指针作为函数名直接调用相关的函数。x=(*p)(a,b);
这种调用方式通过访问函数指针的形式调用相关的函数,它明确指出是通过函数指针而不是函数名调用函数,类型属性清晰明了。
- 定义的函数指针可以先后指向不同的函数
- 变量作为函数参数时,是一种__值传递,形参的变化不影响实参的值。__将变量的指针作为参数是一种__地址传递方式,形参的变化影响实参。__
- 数组的数组名可以作为函数的实参和形参,数组名作为参数是一种地址传递方式,当形参数组中的元素的值发生变化时,实参数组中的元素值也会随之改变。运用数组的指针作为函数参数与数组名作为函数参数作用相同。
- 指向函数的指针变量定义的格式为:
- 函数分为返回值和无返回值两种,有返回值的函数只能带回一个值,返回的值可以是整型、实型、字符型等,指针也是一种类型,因此函数的返回值可以是指针类型。==返回值为指针的函数称为指针函数。==
- 指针函数的定义形式为:
数据类型 *函数名(参数列表); 例如: float *average(float a[ ], int n);
- 指针函数的定义形式为:
指针函数是一个函数,其返回值的类型是一个指针;函数指针是一个指针变量,该指针所指的对象是一个函数。例如:
int (*p)(int,int); /* 函数指针*/ int *sum(int,int); /* 指针函数*/
5.结构体
- 结构体和数组同属于构造数据类型,所不同的是数组是一组相同数据类型元素的集合,组成数组的各成员的类型必须相同。
- struct是结构体类型的关键标识符,同基本数据类型标识符一样
- 结构体名是用户自己为结构体定义的标识符,符合标识符的命名规则。不能使用C语言已经有的关键字。
- 结构体在定义的时候"{}"所包含的项称为结构体的成员列表,这些成员列表与前面的变量定义相同。
- 结构体的最后即"{}"的后面是";",因为结构体定义是C语言的语句,要以";"结束。
- 结构体类型不是由系统定义的,而是由用户定义的,而且结构体类型也不唯一
- 结构体成员可以和程序中的其他变量同名,也可以与另外其他的结构体成员同名。
- 当结构体的成员是结构体时,该结构体为__嵌套结构体__。但需要注意的是,作为成员变量的结构体必须在本结构体之前定义。
- 定义结构体之后在内存中不占内存空间,需要定义结构体类型的变量告诉内存为其分配一定数量的存储空间。
- 定义结构体相当于定义了数据类型,定义了数据类型就可以定义结构体变量,也就是直接定义结构体变量,形式如下:
struct 结构体名 { 数据类型 成员1; 数据类型 成员2; 数据类型 成员3; … 数据类型 成员n; } 变量名列表; 
- 结构体的成员的数据类型不同,在定义时需要一一赋值与数组的初始化类似,按照成员出现的顺序进行逐一赋值,各个值之间用逗号隔开。 就跟数组一样。对一维数组的初始化有两种方式:一种是在数组定义时进行初始化,另一种是先定义数组,然后再对数组元素进行一一赋值。
- 结构体中包括不同类型的成员变量,结构体变量不能作为整体进行引用,对结构体变量的引用是通过引用结构变量的成员而实现的。
- 结构体是一种数据类型,并不占用存储空间,只有当定义了变量或数组以后内存才为其分配存储空间,结构体变量和结构体数组所存储的地址就是结构体变量和结构体数组的指针。
- 结构体变量指针变量的形式如下:
结构体类型 *指针变量名列表;
- 结构体变量指针引用的一般形式为:
(*指针变量名).成员名 指针变量名->成员名
"*"是__取内容运算符__,"*指针变量名"表示的是结构体变量名,相当于使用结构体变量引用其成员。"."是__取成员运算符__,用于获取结构体中的成员。
"->"是指向成员运算符,结构体指针变量直接访问结构体成员。其优先级与取成员运算符"."相同
- 结构体变量指针变量的形式如下:
- malloc()函数进行强制类型转换的形式如下:
(类型说明符*) malloc(size) 类型说明符表示将开辟的存储空间转化成需要的类型。
- free()函数的原型为:
void free(void *p)
- 链表的建立与输入的步骤如下:
(1)定义链表结点结构即指针域与数据域。
(2)建立链表的头结点。
(3)建立链表的结点,并连接到链表头结点后面,并将最后一个结点的指针域置为空(NULL)。
(4)指针定位至链表的头部将链表结点的数据逐一输出。 - 自定义数据类型符的语法格式为:
typedef 原类型名 新类型名;
-
- typedef 数据类型符 自定义数组类型符[数组长度]; 其中,“自定义数组类型符”就是所定义的数组的别名。使用“自定义数组类型符”就可以定义相同数组长度、相同数据类型的数组,因此在定义的时候要指明数组的长度。例如:
typedef in SCORE[10]; SCORE a;
这两个语句的作用就是定义整型数组int[10]的别名用SCORE表示,然后使用SCORE定义一个数组a,表示a是一个具有10个数组元素的整型数组,等价于int a[10]。
- typedef 数据类型符 自定义数组类型符[数组长度]; 其中,“自定义数组类型符”就是所定义的数组的别名。使用“自定义数组类型符”就可以定义相同数组长度、相同数据类型的数组,因此在定义的时候要指明数组的长度。例如: