本文主要是介绍【数据结构】01-绪论《数据结构 C语言版(严蔚敏、吴伟民)》,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 教材 > 第1章 绪论
- 1.1 什么是数据结构
- 1.2 基本概念和术语
- 1.3 抽象数据类型的表示与实现
- 1.4 算法和算法分析
- 习题集 > 第1章
- 二、算法设计题
- 附 > 友情推荐链接
教材 > 第1章 绪论
1.1 什么是数据结构
- 用计算机解决一个具体问题时的步骤:
- 首先,从具体问题抽象出一个适当的数学模型
- 然后,设计一个解此数学模型的算法(分析问题,提取操作对象,找出对象之间关系,用数学语言描述)
- 最后,编写程序,进行测试,调整直至得到最终解答
- 数据结构:是一门研究非数值计算的程序设计问题中计算机的操作对象以及他们之间的关系和操作等的学科;
1.2 基本概念和术语
- 数据:对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称
- 数据元素:是数据的基本单位,一个数据元素可由若干个 数据项(是数据的不可分割的最小单位)组成
- 数据对象:是性质相同的数据元素的集合,是数据的一个子集
- 数据结构:是相互之间一种或多种特定关系的数据元素的集合
- 基本结构:(数据元素之相互之间的关系 == 结构)
- 集合
- 线性结构(一对一)
- 树形结构(一对多)
- 图状结构或网状结构(多对多)
- 形式定义:Data Structure =(D,S)
- 逻辑结构(数学模型结构定义中的关系)
- 顺序映像
- 非顺序映像
- 存储结构(存储映射)(位、元素、数据域)
- 顺序存储结构(数组)
- 链式存储结构(指针)
- 任何一个算法的设计取决于选定的数据(逻辑)结构,而算法的实现依赖于采用的存储结构
- 虚拟存储结构 和 数据类型
- 原子类型
- 结构类型
- 抽象数据结构(由一个值域和定义在该值域上的一组操作组成)
- 原子类型
- 固定聚合类型
- 可变聚合类型 ADT = (D,S,P)
- 多形数据结构
1.3 抽象数据类型的表示与实现
- ADT:利用处理器中已存在的数据类型来说明新的结构,用已经实现的操作来组合新的操作
1.4 算法和算法分析
- 算法 — 是对特定问题求解步骤的一种描述;
- 算法特性
- 有穷性:一个算法必须总是(对任何合法的输入值)在执行有穷步之后结束,且每一步都可在有穷时间内完成
- 确定性:算法中每一条指令必须有确切的含义,读者理解时不会产生二义性。并且,在任何条件下,算法只有唯一的一条执行路径,即对相同的输入只能得出相同的输出
- 可行性:一个算法是能行的,即算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现的
- 输入:有零或多个输入
- 输出:有一个或多个输出
- 算法的设计要求
- 正确性:应当满足具体问题的需求
- 不含语法错误
- 对于几组输入能得到满足规格的结果
- 对于精心选择的典型、苛刻而带有刁难性的输入能够得到满足规格的结果
- 对于一切合法的输入数据都能得到满足规格的结果
- 可读性:首先为了人的阅读和交流,其次才是极其执行
- 健壮性:处理错误的方法应是返回一个表示错误或错误性质的值,而不是打印错误信息或异常
- 效率与低存储量需求:
- 正确性:应当满足具体问题的需求
- 算法效率的度量
- 方法
- 事后统计
- 事前分析估算
- 一句算法选用何种策略
- 问题的规模
- 程序语言
- 编译程序所产生的机器代码的质量
- 机器执行指令的速度
- 时间复杂度:T(n) = O(f(n))
- 一个算法是由控制结构和原操作构成的,算法的时间取决于两者的综合效果
- 空间复杂度:S(n) = O(f(n))
- 方法
习题集 > 第1章
二、算法设计题
1.16 试写一算法,自大到小依次输出顺序读入的三个整数X,Y和Z的值。
// 文件名:1_16.c#include <stdio.h>void order(int a, int b, int c){printf("In descending order:\r\n");printf("orgin: a=%d, b=%d, c=%d\r\n", a, b, c);if(a < b){a += b;b = a - b;a = a - b;}if(b < c){b += c;c = b - c;b = b - c;}if(a < b){a += b;b = a - b;a = a - b;}printf("sorted: a=%d, b=%d, c=%d\r\n", a, b, c); }int main(){int a = 11;int b = 99;int c = 66;order(a, b, c);return 0; }
# 运行结果 ubuntu@ubuntu:~/work/c/algo$ vim 1_16.c ubuntu@ubuntu:~/work/c/algo$ gcc 1_16.c ubuntu@ubuntu:~/work/c/algo$ ./a.out In descending order: orgin: a=11, b=99, c=66 sorted: a=99, b=66, c=11 ubuntu@ubuntu:~/work/c/algo$
1.17 已知k阶斐波那契序列的定义为
f0=0, f1=0, …, fk-2=0, fk-1=1;
fn=fn-1+fn-2+…+fn-k, n=k,k+1,…
试编写求k阶斐波那契序列的第m项值的函数算法,k和m均以值调用的形式在函数参数表中出现。
// 注:K阶斐波那契数列的前K-1项均为0,第k项为1,以后的每一项都是前K项的和 // 文件名:1_17.c #include <stdio.h>// 求值(递归) int k_fib(int k, int m){// 因为第 k-1 项为0,所以此处 k 最小取2if((m<0) || (k<2)){return -1;}int i, v;if((k-1) > m){return 0;}else if((k-1) == m){return 1;}else{for(i=1, v=0; i<=k; i++){v += k_fib(k, m-i);}return v;} }int main(){int k, m, v;// 1. k < mk = 4;m = 7;v = k_fib(k, m);if(v < 0){printf("error, please check the value of k and m.");}else{printf("if k=%d, m=%d; fib(m) = %d\r\n", k, m, v);}// 2. k == mk = 11;m = 11;v = k_fib(k, m);if(v < 0){printf("error, please check the value of k and m.");}else{printf("if k=%d, m=%d; fib(m) = %d\r\n", k, m, v);}// 3. k > mk = 11;m = 5;v = k_fib(k, m);if(v < 0){printf("error, please check the value of k and m.");}else{printf("if k=%d, m=%d; fib(m) = %d\r\n", k, m, v);}return 0; }
# 运行结果 ubuntu@ubuntu:~/work/c/algo$ vim 1_17.c ubuntu@ubuntu:~/work/c/algo$ gcc 1_17.c ubuntu@ubuntu:~/work/c/algo$ ./a.out if k=4, m=7; fib(m) = 8 if k=11, m=11; fib(m) = 1 if k=11, m=5; fib(m) = 0 ubuntu@ubuntu:~/work/c/algo$
拓展:斐波那契数列
1.18 假设有A、B、C、D、E五个高等院校进行田径对抗赛,各院校的单项成绩均已存入计算机,并构成一张表,表中每一行的形式为
项目名称 性别 校名 成绩 得分 编写算法,处理上述表格,以统计各院校的男、女总分和团体总分,并输出。
// 注:首先结构化表格,采集数据,根据定义的数据结构计算目标值 // 文件名:1_18.c #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h>typedef enum{FEMALE,MALE }SexType;typedef enum{A,B,C,D,E }SchoolName;typedef struct{char sport; // 项目名称int gender; // 性别(女:0;男:1)SchoolName school_name; // 校名为'A','B','C','D'或'E'char result; // 成绩int score; // 得分 }ResultType;typedef struct{int male_score; // 男子总分int female_score; // 女子总分int total_score; // 男女团体总分 }ScoreType;void Scores(ResultType *result, ScoreType *score, int num){ int i = 0;for(i=0; i<num; i++){int n = result[i].school_name + 1;score[n].total_score += result[i].score;if(result[i].gender == 1){score[n].male_score += result[i].score;}else{score[n].female_score += result[i].score;}} }int main(){ int i, n;ResultType *result;ScoreType score[5] = {0};printf("请输入各院校参赛的总人数:");scanf("%d", &n);result = malloc(n * sizeof(ResultType));memset(result, 0, n*sizeof(ResultType));printf("请输入各院校运动员的项目名称、性别、校名、成绩、得分:\n");int school_type;for(i=0; i<n; i++){setbuf(stdin, NULL);printf("< 运动员%d >\n", i+1);setbuf(stdin, NULL);printf("输入项目:\n");scanf("%c", &result[i].sport);setbuf(stdin, NULL);printf("输入性别:\n");scanf("%d", &result[i].gender);setbuf(stdin, NULL);printf("输入校名:\n");scanf("%d", &school_type);result[i].school_name = school_type;setbuf(stdin, NULL);printf("输入结果:\n");scanf("%c", &result[i].result);setbuf(stdin, NULL);printf("输入分数:\n");scanf("%d", &result[i].score);printf("GET: %c %d %d %c %d\r\n", result[i].sport, result[i].gender,result[i].school_name, result[i].result, result[i].score);}Scores(result, score, n);for(i=0; i<5; i++){printf("the school %d: \r\n", result[i].school_name) ; printf("Total score of male: %d\r\n", score[i].male_score);printf("Total score of female: %d\r\n", score[i].female_score);printf("Total score of all: %d\r\n\n", score[i].total_score);}return 0; }
# 运行结果 ubuntu@ubuntu:~/work/c/algo$ gcc 1_18.c ubuntu@ubuntu:~/work/c/algo$ ./a.out 请输入各院校参赛的总人数:2 请输入各院校运动员的项目名称、性别、校名、成绩、得分: < 运动员1 > 输入项目: A 输入性别: 0 输入校名: 1 输入结果: S 输入分数: 88 GET: A 0 1 S 88 < 运动员2 > 输入项目: B 输入性别: 1 输入校名: 1 输入结果: S 输入分数: 99 GET: B 1 1 S 99 the school 1: Total score of male: 0 Total score of female: 0 Total score of all: 0the school 1: Total score of male: 0 Total score of female: 0 Total score of all: 0the school 0: Total score of male: 99 Total score of female: 88 Total score of all: 187the school 0: Total score of male: 0 Total score of female: 0 Total score of all: 0the school 0: Total score of male: 0 Total score of female: 0 Total score of all: 0ubuntu@ubuntu:~/work/c/algo$
*1.19 试编写算法,计算i!*2i的值并存入数组a[0…arrsize-1]的第i-1个分量中(i=1,2,…,n)。假设计算机中允许的整数最大值为maxint,则当n>arrsize或对某个k(1≤k≤n)使k!2k>maxint时,应按出错处理。注意选择你认为较好的出错处理方法。
// 注:重点是错误返回和处理 // 文件名:1_19.c #include <stdio.h> #include <limits.h>#define OVERFLOW (-2) #define ERROR (-1) #define OK 0#define arrsize 100 #define max_int INT_MAXint calc(int i, int *arr){if(i<1 || i>arrsize){return ERROR;}printf("calc %d!*2^%d :\r\n", i, i);int j;for(j=1; j<i; j++){if(j == 1){arr[j-1] = 2;}else{if(max_int/(1*j) < arr[j-2]){return OVERFLOW;}arr[j-1] = 2 * j * arr[j-2];}}printf("< i = %d, i!*2^i > arr[i-1] = %d\r\n", i, arr[j-1]);return OK; }int main(){int i, res[arrsize];i = 6;int ret = calc(i, res);if(ret == OK){printf("OK!\r\n");}else if(ret == OVERFLOW){printf("overflow.\r\n");}else if(ret == ERROR){printf("error.\r\n");}else{printf("unknown error.\r\n");}return 0; }
# 运行结果 ubuntu@ubuntu:~/work/c/algo$ vim 1_19.c +27 ubuntu@ubuntu:~/work/c/algo$ gcc 1_19.c ubuntu@ubuntu:~/work/c/algo$ ./a.out calc 6!*2^6 : < i = 6, i!*2^i > arr[i-1] = 32767 OK! ubuntu@ubuntu:~/work/c/algo$
1.20 试编写算法求一元多项式的值Pn(x),并确定算法中每一语句的执行次数和整个算法的时间复杂度。注意选择你认为较好的输入和输出方法。本题的输入为ai(i=0,1,…,n),x0和n,输出为Pn(x0)。
// 注:多项式求和,重点是计算次数和时间复杂度 // 文件名:1_20.c #include <stdio.h> #include <math.h>int calc(int *a, int x, int n){int i, res;for(i=1, res=0; i<=n; i++){res += a[i-1]*pow(x, i-1); // 执行 n 次,时间复杂度O(n)}return res; }int main(){int a[8] = {3, 4, 8, -2, 1, 5, 7, 6};int n = sizeof(a)/sizeof(a[0]);int x = 2;printf("P%d(%d) = %d\r\n", n, x, calc(a, x, n));return 0; }
# 运行结果 ubuntu@ubuntu:~/work/c/algo$ vim 1_20.c ubuntu@ubuntu:~/work/c/algo$ gcc 1_20.c -lm ubuntu@ubuntu:~/work/c/algo$ ./a.out P8(2) = 1419 ubuntu@ubuntu:~/work/c/algo$
附 > 友情推荐链接
- 很不错的课本及习题解析:https://www.cnblogs.com/kangjianwei101/p/5221816.html
- 教材第一章:https://www.cnblogs.com/kangjianwei101/p/5222014.html
- 习题第一章:https://www.cnblogs.com/kangjianwei101/p/5222150.html
—— 2018-11-27 ——
这篇关于【数据结构】01-绪论《数据结构 C语言版(严蔚敏、吴伟民)》的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!