Upload
kane-brock
View
136
Download
7
Embed Size (px)
DESCRIPTION
数据结构 DATA STRUCTURE. —— C 语言描述. 胡 海 EMail : [email protected]. 引 数据结构讨论的范畴 —— 数据抽象. 实体 信息 数据. 引 数据结构讨论的范畴 —— 程序设计. Niklaus Wirth Algorithm + Data Structures = Programs. 程序设计: 为计算机处理问题编制 一组指令集 算法: 怎样处理? —— 处理问题的策略 数据结构: 信息怎样表示? —— 数学模型. - PowerPoint PPT Presentation
Citation preview
引 数据结构讨论的范畴——数据抽象
实体 信息 数据
引 数据结构讨论的范畴——程序设计
Niklaus Wirth Algorithm + Data Structures = Programs程序设计:为计算机处理问题编制
一组指令集
算法: 怎样处理?——处理问题的策略
数据结构:信息怎样表示?——数学模型
引 数据结构讨论的范畴——数据结构
1 数值计算问题:
线性代数方程、常微分方程
2 非数值计算问题:
数据结构描述现实世界实体的数学模型及其上的操作在计算机中的表示和实现
数据结构的重要性
• 现实世界 计算机世界的桥梁• 程序设计的根本所在• 信息科学的基础• GIS学科研究的核心内容之一• IT企业考察技术能力的关键
注意事项 最终成绩:作业 + 上机实习报告 + 考勤 + 考试
按时按量完成作业,不要抄袭,就算抄也要动着脑筋抄
学过的内容有条件的话尽量编程实现
作业用本子不要纸方便留作资料;随身携带,会有随堂作业
课内参考书目1. 数据结构 (C 语言版 ) ,严蔚敏 吴伟民,
清华大学出版社, 1997 年 4 月第一版2. 数据结构题集 (C 语言版 ) ,严蔚敏 吴伟
民,清华大学出版社, 1999 年 2 月第一版
3. 数据结构 ——使用 c 语言,朱站立,西安交大出版社
第 0 章 结构化程序设计、 c 语言重点回顾
主要知识点
计算机、程序设计的本质 内存地址、指针
typedef 类型定义 结构体 函数及其运行机制,头文件
动态内存分配 程序调试
什么是“计算机”?图灵机 1937 (计算机理论之父)
是么是 “算法” ? 问题的可计算性 人工智能的界限
冯 · 诺依曼思想 1946 (现代计算机之父) 1. 用二进制代码表示程序和数据; 2. 计算机采用存储程序的工作方式; 3. 计算机硬件由存储器、运算器、控制 器、
输入设备和输出设备组成。
结构化程序设计使用顺序结构、选择结构、循环结构以及它们的组合来组织一个程序。采用自顶向下逐步求精的方法编写程序。
求两整数的最大公约数和最小公倍数
主要知识点
计算机、程序设计的本质 内存地址、指针
typedef 类型定义 结构体 函数及其运行机制
动态内存分配 程序调试
int main( ){
char a = ‘A’;
int b = 1;
float c = 2;
double d = 3;
return 0;
}
650000002 a
00000003
0b
0000004
0000005 0
1
0
0c
0000006
0000007
0000008
0
2
0000009
0000010
内存地址
值:内存单元中存放的数据地址:系统分配给变量的内存单元的起始地址
指针变量存放地址的变量称为指针变量,它用来指向另一个变量,通常用 * 表示。
int main()
{
int i=65;
int *i_pointer;
i_pointer = &i;
return 0;
}
0
0000002
0000002
000000E
650000004
& :取变量的首地址,即指针;
* :取指针所指向的地址中的值;
int i, j, *p;
p=&i;
*p=3;
j=*p+2;
1000
1004
1008
i
j
p
定义后
1000
1004
1008 1000
i
j
p
p=&i
31000
1004
1008 1000
i
j
p
*p=3
31000
1004
1008
5
1000
i
j
p
j=*p+2
指针操作
主要知识点
计算机、程序设计的本质 内存地址、指针
typedef 类型定义 结构体 函数及其运行机制,头文件
动态内存分配 程序调试
内存管理和函数调用计算机采用存储程序的工作方式
程序内各成分在计算机中的存储: 代码段(程序) 数据段(全局、静态) 系统栈(局部、形参) 堆 (动态)
函数调用中究竟发生了什么?
main 函数
调用 a 函数
结束
a 函数
调用 b 函数
b 函数
①② ③ ④
⑤
⑥⑦⑧
⑨
( 1 )为所有的形参分配内存,计算各个实际参数表达式的值,依次赋予对应的形式参数。(若是“无参函数”,上述工作不执行)( 2 )进入函数体,执行函数中的语句,实现函数的功能,当执行到“返回语句”时,计算返回值,释放本函数体中的变量等(静态型变量不释放),收回分配给形参的内存,返回主调函数。( 3 )继续执行主调函数中的后继语句。
参数传递 函数间传递数据有四种方式:值传递方式;地址传递方式;返回值传递方
式;全局变量传递。
例设计一个数据交换函数swap( ),实现两个数的交换
void swap(int a, int b){
int temp;
temp = a;
a = b;
b = temp;
}
int main(){
int m, n;
scanf(“%d %d”, &m, &n);
swap(m, n);
printf(“%d %d”, m, n);
return 0;
}
void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main(){
int m, n;
scanf(“%d %d”, &m, &n);
swap(&m, &n);
printf(“%d %d”, m, n);
return 0;
}
10000002
0000012
20000006
m
n
00000002
00000006
a
b
0000016
000001A
temp
void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
主要知识点
计算机、程序设计的本质 内存地址、指针
typedef 类型定义 结构体 函数及其运行机制,头文件
动态内存分配 程序调试
结构体结构体类型的说明一个结构体类型由若干个称为成员的成分组成,其类型说明的一般形式为:struct 结构体标识名{类型名 1 结构体成员名 1 ; 类型名 2 结构体成员名 2 ; …… 类型名 n 结构体成员名 n ;};
其中, struct 是关键字,结构体名和结构成员名是用户定义的标识符。注意必须在结尾加分号,因为结构体类型声明本身为一条语句。
依此格式,可以说明如下结构体类型来描述上述学生档案信息:struct student
{ char name[20];
int code;
char sex;
int age;
char address[40];
};
结构体变量成员的引用 若已定义了结构体变量,使用成员运算符“ .” 来访问结构体成员,形式如下: 结构体变量名 . 成员名假设有如下定义:struct person{ char name[20]; long int code ; char sex; struct {int day,month,year;}birthday; char address[40]; } std1,std[3];则: std1.code 引用结构体变量std1 中的成员 code, std[1].code 引用结构体数组 std中第二个元素 std[1] 的成员 code 。
若定义了基类型为结构体类型的指针变量,可以用成员运算符“ .” 和结构指向运算符“ ->” 两种方式引用,形式如下:
指针变量名 -> 成员名 (* 指针变量名 ). 成员名
假设有如下语句:struct person std1,*pstd;pstd=&std1;
则引用结构体变量 std1 的成员 code ,可写成:pstd->code(*pstd).num
用 结构体 + 指针 实现的链式单元
指针域数据域数据域 nextdatadata或
数据域:存储元素数值数据
指针域:存储直接后继的存储位置
结点结构如图示:
typedef struct Node
{
DataType data;
struct Node *next;
}SLNode;
a0head
a1 … an ^
主要知识点
计算机、程序设计的本质 内存地址、指针
typedef 类型定义 结构体 函数及其运行机制,头文件
动态内存分配 程序调试
Typedef 的用途 代码简化 (别名)
struct tagPOINT1 { int x; int y; }; struct tagPOINT1 p1;
typedef struct tagPOINT { int x; int y; }POINT;
POINT p1; // 这样就比原来的方式少写了一个 struct ,比较省事,尤其在大量使用的时候
跨平台开发
主要知识点
计算机、程序设计的本质 内存地址、指针
typedef 类型定义 结构体 函数及其运行机制
动态内存分配 程序调试
动态内存分配函数简介 动态内存分配 在前面的程序设计中,存在一个问题,就是
在编写程序时,因为无法确定要处理数据的规模,在定义变量时就为它说明一个特别大的空间,这对内存资源利用和程序设计都是不利的。我们希望,计算机能按需分配内存,在运行时需要多大的空间就分配多大的空间。
上面提出的问题,实际上是计算机内存的动态管理问题。
动态内存分配函数malloc() 函数 其函数原型为: void *malloc(unsigned int size);
其功能是:分配一块长度为 size 字节的连续空间,并将该空间的首地址作为函数的返回值。如果函数没有成功执行,返回值为空指针( NULL 或 0 )。由于返回的指针的基类型为void ,应该通过显式类型转换后才能存入其他基类型的指针变量中,否则会有警告提示。
例如:int *p;
p=(int *)malloc(sizeof(int));
动态内存分配函数free() 函数其函数原型为: void free(void *block);
其功能是:释放以前分配给指针变量 block 的动态空间,但指针变量 block 不会自动变成空指针。
数组(静态、动态)和指针
静态 : int x; int A[10]; int y;
动态 : int x; int *pA; int y;
动态数组定义和使用流程
1. 定义指针(数组名) Datatype *pA;
2. 分配内存空间 pA= ( Datatype * ) malloc(sizeof(Datatype)* 数组大小) ) ;
3. 初始化 for ( ;; ) pA[i] = …
4. 使用5. 结束前释放空间 free(pA); pA=NULL;
二维动态数组内存分配示意图
动态分配常犯的错误1 )内存分配未成功,却使用了它。 2 )内存分配虽然成功,但是尚未初始化就引用它。 3 )内存分配成功并且已经初始化,但操作越过了内存的边界。 4 )忘记了释放内存,造成内存泄露。 5 )释放了内存却继续使用它。
有三种情况:A 程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。B 函数的 return 语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。C 使用 free 或 delete 释放了内存后,没有将指针设置为 NULL 。导致产生“野指针”。
主要知识点
计算机、程序设计的本质 内存地址、指针
typedef 类型定义 结构体 函数及其运行机制
动态内存分配 程序调试
文件输入输出
fopen fprintffscanf fclose
fwritefread
程序调试 程序执行期行进控制
1 )单步行进(跳过函数 step over ) 2 )进入函数 ( Step into ) 3 )运行到光标
参数监控
作 业P13 0-5 , 补 1 :有: int x=1 , y=2 ; 编制函数交换两者的值。 补 2 :有: struct student{ long Number;…..} 1 )写出动态分配 100 个 student 空间的语句 2 )绘制动态分配 5*4 二维 int 数组的内存空
间示意图,并写出对应语句
上机实习学生信息管理: 从文件读写本班同学信息记录。从“ GIS3.txt” ,读出数据,
写入到“ newGIS3.txt”要求: 1 )学生记录:学号,姓名,年龄,身高; 2 )工程由 3 个文件组成: main.c; Stu.h; Stu.c 3 )学生记录使用动态数组管理 4 )交换第一位与最后一位同学的全部信息并输出到
( swapGIS3.txt )
上机前本班学习委员 按照学号次序组织本班 XXX.txt 文件时间地点:第二周 周 5 ( 9 月 18日) 1~2 节 资环院 4 楼机房
1.int,int*; char,char*; double,double*; student(自定义) ,student*….,这些数据类型各占用多少内存,编程验证之。
2.为什么 c 语言中定义数组如: double a[NUM]; 时, NUM必须为常数?试从内存分配的角度讨论一下。
3.下面的程序: Test 函数的语句 GetMemory(str, 200) 并没有使 str获得期望的内存, str依旧
是 NULL ,为什么?如何修改?
void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(char) * num); }
void Test(void) { char *str = NULL; GetMemory(str, 100); // str 仍然为 NULL strcpy(str, “hello”); // 运行错误 }
补充思考题:
二维动态数组内存分配示意图