本数据结构系列文章均参考西安交通大学出版的数据结构一书,由朱战立编著。
0.1程序的结构
写文章要考虑文章的结构,编写程序也要考虑程序的结构.程序是处理特定问题的用程序设计语言书写的语句序列.当要处理的问题复杂时,程序将会很长.因此,程序的结构就非常重要.
C语言程序的结构一般如下:
函数1
函数2
…
函数n
主函数
函数分为库函数和用户自定义函数两大类.库函数也称作系统函数,是包括在高级语言软件中的提供基础功能的函数.用户自定义函数是软件开发者根据所处理的特定问题设计的提供特定功能的函数.
0.2函数
C语言函数的一般形式为:
数据类型 函数名(数据类型 参数1,……,数据类型 参数n)
{
函数体
}
一个函数由函数名,参数和函数体三部分组成.
0.2.1 返回值
一个函数的函数名既是该函数的代表,同时也是一个变量.系统为函数名变量分配有与定义的数据类型相一致的内存单元空间.由于函数名变量是像全局变量一样定义的,所以调用函数可以使用保存在函数名变量中的数据.由于函数名变量通常用来把函数的处理结果数据带回给调用函数,所以一般把函数名变量称为返回值.
例:0-1设计一个从两个整数类型数据中得到较大数值的函数,并设计一个主函数调用该函数.
#include
int Max1(int x1, int x2)
{
if (x1 >= x2) return x1;
else return x2;
}
void main(void)
{
int t1 = 5, t2 = 8, max;
max = Max1(t1, t2);
printf("Max = %d\n",max);
}
//Max = 8
0.2.2 输入型参数
输入型参数是指调用函数只通过该参数传送数据给被调用函数.由于调用函数只向被调用函数传送数据所以称为输入型参数.输入型参数也称作值参.
0.2.3 输出型参数
输出型参数是指调用函数只通过该参数把被调用函数处理后得到的结果数据传送给调用函数.由于这样的参数数据是离开被调用函数的,所以称为输出型参数.输出型参数也称作变参.
例0-2 设计一个从三个整数类型数据中得到最大数值和次大数值的函数.
#include
void Max2(int x1, int x2, int x3, int *y1, int *y2)
{
//注意:输出型参数y1和y2定义为指针类型
if (x1 >= x2 && x1 >= x3)
{
*y1 = x1;
if (x2 >= x3) *y2 = x2;
else *y2 = x3;
}
if (x1 >= x2 && x1 < x3)
{
*y1 = x3;
if (x1 >= x2) *y2 = x1;
else *y2 = x2;
}
if (x1 < x2 && x2 >= x3)
{
*y1 = x2;
if (x1 >= x3) *y2 = x1;
else *y2 = x3;
}
if (x1 < x2 && x2 < x3)
{
*y1 = x3;
if (x1 >= x2) *y2 = x1;
else *y2 = x2;
}
}
void main(void)
{
int v1 = 5, v2 = 9, v3 = 7, f1, f2;
Max2(v1,v2,v3,&f1,&f2);
printf("f1 = %d f2 = %d\n",f1,f2);
}
//f1 = 9 f2 = 7
0.3结构体
高级程序设计语言中都只定义了如int,long,float,char等基本数据类型,在有些程序设计问题中,需要把若干个基本类型的数据作为一个整体来考虑,在C语言中,这样的问题是通过结构体定义语句来解决的.结构体定义语句的一般格式为:
struct <结构体名>
{
<成员列表>
};
示例:
struct Student
{
long number; //学号
char name[10]; //姓名
char sex[3]; //性别
int age; //年龄
};
//对结构体类型的变量,既可以整体处理,也可以按成员分量处理.
struct Student x = {100001,"张三","男",26},y,*p;
0.4自定义语句
自定义语句的功能是把一个已定义的数据类型名换为一个新的数据类型名.自定义语句的格式为:
typedef <已定义的数据类型名> <新的数据类型名>;
例0-3:设计一个对任意基本类型的两个数据,求其中较大的值.
#include
typedef float DataType;
DataType Max3(DataType x1, DataType x2)
{
if (x1 >= x2) return x1;
else return x2;
}
void main(void)
{
DataType t1 = 5.1, t2 = 8.8, max;
max = Max3(t1, t2);
printf("Max = %f\n",max);
}
//Max = 8.800000
0.5 动态内存分配
C语言支持动态内在分配.C语言的函数库中包含了一组可以在程序运行时要求系统分配内存空间的函数.这些函数主要是malloc()函数,free()函数,calloc()函数和realloc()函数.这些函数一般存放在头文件malloc.h中
malloc()函数的原型是:
void * malloc(unsigned size)
malloc()函数用于向系统动态申请size个字节的内存单元空间,函数返回值为所申请的内存空间首地址.
free()函数的原型是:
void free(void*p)
free()函数用于释放动态分配的内存空间.在程序中,用malloc()函数或用其他动态内存申请函数申请的内存空间要用一个指针类型的变量指示其首地址,假设该首地址用指针变量p指示,若将p作为实参调用free()函数,则实现释放指针变量p指示的动态申请函数所申请的内存空间.
示例0-4 设计一个用动态数组保存字符串”Data Structure”的程序
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
void main(void)
{
int length = 100;//length为动态数组的元素个数
char*str, s1[] = {"Data Structure"};
int i, n;
str = (char*)malloc(sizeof(char)*length);
strcpy(str, s1);
n = strlen(str);
printf("str length %d\n",n);
printf("str = ");
for (i = 0; i < n; i++)
printf("%c",str[i]);
free(str);
}
/*
str length 14
str = Data Structure
*/
0.6 一个程序例子
例0-5:设计一个可以在数组中插入任意多个任意数据类型数据的函数,然后设计一个主函数在该数组中插入10个整数类型的数据.要求把主函数设计为一个文件,把其余部分设计为另一个文件.
SeqList.h
typedef struct{
DataType list[MaxSize]; //存放数据的数组成员
int size; //记录数组当前个数的成员
} SeqList; //命名该结构体为SeqList
//要能方便地操作和管理数组中的数据,需要设计对数组元素个数变量进行初始化操作的函数,
//求数组当前个数的函数,在数组的任意位置插入数据的函数以及取数 组的任意位置上数据的函数.
void ListInitiate(SeqList*L)
{
L->size = 0; //定义初始数据元素个数
}
int ListLength(SeqList L)
{
return L.size;
}
int ListInsert(SeqList*L, int i, DataType x)
{
//在数组的位置i(0<=i<=size)前插入数据元素x函数
//插入成功时函数返回1,否则返回0
int j;
if (L->size >= MaxSize)
{
printf("数组已满无法插入!\n");
return 0;
}
else if (i < 0 || i > L->size)
{
printf("参数i不合法!\n");
return 0;
}
else
{
//为插入做准备
for (j = L->size; j > i; j--)
L->list[j] = L->list[j - 1];
L->list[i] = x;
L->size++;
return 1;
}
}
int ListGet(SeqList L, int i, DataType *x)
{
if (i < 0 || i > L.size - 1)
{
printf("参数i不合法!\n");
return 0;
}
else
{
*x = L.list[i];
return 1;
}
}
SeqList.c
#include
#define MaxSize 100
typedef int DataType;
#include"SeqList.h"
void main(void)
{
SeqList myList;
int i, x, n = 10;
int a[10] = {1,2,3,4,5,6,7,8,9,10};
ListInitiate(&myList);
for (i = 0; i < n; i++)
{
if (ListInsert(&myList, i, a[i]) == 0)
{
printf("错误!\n");
return;
}
}
n = ListLength(myList);
for (i = 0; i < n; i++)
{
if (ListGet(myList, i, &x) == 0)
{
printf("错误!\n");
return;
}
else
{
printf("%3d",x);
}
}
printf("\n");
}
// 1 2 3 4 5 6 7 8 9 10