数据结构-1 基本概念
来源:互联网 发布:大数据服务平台开放 编辑:程序博客网 时间:2024/06/05 16:06
数据结构起到承上启下的作用,上承计算机基础和C语言等基础内容,下启算法设计与分析、操作系统、编译原理、数据库原理等核心内容。
数据结构的内容包括各种数据(线性表、栈、队列、串、数组、数、二叉树和图等)的逻辑结构描述、存储结构表示和运算算法设计,其主要是基本算法的设计,而算法设计与分析主要是通用算法的设计。
1. 什么是数据结构?
1.1 解决问题方法的效率跟数据的组织方式有关
例1:如何在书架上摆放图书?(这个问题不科学)
问题分析:图书的摆放影响图书的插入和查找操作!可以有如下三种摆放方式:
①. 随便放:插入方便,但查找累死;
②. 按照书名的拼音字母顺序摆放:二分查找,但插入累死;
③. 把书架划分成几块区域,每块区域指定摆放某种类别的图书,同类别内按书名的拼音字母顺序摆放;先定类别再二分查找,先定类别再二分查找确定位置后移出空位。
问题总结:图书的组织方式影响其操作效率;空间问题+类别划分问题:图书应该分为多少个类别,每个类别应该分配多少书架呢?
1.2 解决问题方法的效率跟空间的利用效率有关
例2:写程序实现PrintN函数,使得传入一个正整数为N的参数后,能顺序打印从1到N的全部正整数。
问题分析:循环实现、递归实现(代码简洁,但耗费内存空间,可对比N=1000000的情况)。
#include <stdio.h>void printN1(int m);void printN2(int n);int main(void) { int N; scanf("%d",&N); printN2(N); system("pause"); return 0;}/* 循环实现 */void printN1(int m) { int i; for(i=1;i<=m;i++) { printf("%d\n",i); } return;}/* 递归实现:耗费内存资源 当n过大时可能导致系统崩溃 */void printN2(int n) { if(n) { printN2(n-1); printf("%d\n",n); } return;}
1.3 解决问题方法的效率跟算法的巧妙程度有关
例3:计算给定多项式在给定点x处的值。
问题分析:多项式分解法求解速度较快,比直接求解法快一个数量级。
/* 直接求解法 */double f1(int n, double a[], double x){ int i; double sum = a[0]; for(i = 1; i <= n; i++) { sum += (a[i]*pow(x, i)); } return sum;} /* 多项式分解法:速度较快 */double f2(int n, double a[], double x) { int i; double sum = a[n]; for(i = n; i > 0; i--) { sum = a[n-1] + x*sum; } return sum;}
1.4 什么是数据结构?
- 数据对象在计算机中的组织方式(逻辑结构和物理存储结构);
- 数据对象必定与一系列加在其上的操作相关联;
- 完成这些操作所用的方法就叫做算法;
1.5 抽象数据类型(Abstract Data Type)
- 数据类型
- 数据对象集
- 数据集合相关联的操作集
- 抽象:描述数据类型的方法不依赖于具体实现
- 与存放数据的机器无关
- 与数据存储的物理结构无关
- 与实现操作的算法和编程语言无关
- 注意:只描述数据对象集和操作集“是什么”,而不涉及“如何实现”的问题。
2. 什么是算法?
2.1 什么是算法(Algorithm)?
- 一个有限指令集
- 接受一些输入(有些情况下不需要输入)
- 产生输出
- 一定在有限步骤之后终止
- 每一条指令必须
- 有充分明确的目标,不可以有歧义
- 计算机能处理的范围之内
- 描述应不依赖于任何一种计算机语言以及具体的实现手段
2.2 什么是好的算法?
空间复杂度
如例2所示,PrintN(int N)函数的递归实现(
时间复杂度
如例3所示,因计算机计算加减法的速度远大于乘除法,故可只考虑乘除法的计算次数;直接求解法
因此,在分析一般算法的效率时,我们通常关注最坏情况复杂度
2.3 复杂度的渐进表示法
2.4 复杂度分析小窍门
- 若两段算法分别有复杂度
T1(n)=O(f1(n) 和T2(n)=O(f2(n) ,则T1(n)+T2(n)=max{O(f1(n),O(f2(n)} T1(n)×T2(n)=O(f1(n)×f2(n))
- 若
T(n) 是关于n 的k 阶多项式,那么T(n)=Θ(nk) - 一个for循环的复杂度等于循环次数乘以循环体代码的复杂度
- if-else结构的复杂度取决于if条件判断的复杂度和两个分支部分的复杂度,总体复杂度取三者中最大
3. 应用实例:最大子列和问题
给定
3.1 算法1
3.2 算法2
3.3 算法3:分而治之
int Max3( int A, int B, int C ){ /* 返回3个整数中的最大值 */ return A > B ? A > C ? A : C : B > C ? B : C;}int DivideAndConquer( int List[], int left, int right ){ /* 分治法求List[left]到List[right]的最大子列和 */ int MaxLeftSum, MaxRightSum; /* 存放左右子问题的解 */ int MaxLeftBorderSum, MaxRightBorderSum; /*存放跨分界线的结果*/ int LeftBorderSum, RightBorderSum; int center, i; if( left == right ) { /* 递归的终止条件,子列只有1个数字 */ if( List[left] > 0 ) return List[left]; else return 0; } /* 下面是"分"的过程 */ center = ( left + right ) / 2; /* 找到中分点 */ /* 递归求得两边子列的最大和 */ MaxLeftSum = DivideAndConquer( List, left, center ); MaxRightSum = DivideAndConquer( List, center+1, right ); /* 下面求跨分界线的最大子列和 */ MaxLeftBorderSum = 0; LeftBorderSum = 0; for( i=center; i>=left; i-- ) { /* 从中线向左扫描 */ LeftBorderSum += List[i]; if( LeftBorderSum > MaxLeftBorderSum ) MaxLeftBorderSum = LeftBorderSum; } /* 左边扫描结束 */ MaxRightBorderSum = 0; RightBorderSum = 0; for( i=center+1; i<=right; i++ ) { /* 从中线向右扫描 */ RightBorderSum += List[i]; if( RightBorderSum > MaxRightBorderSum ) MaxRightBorderSum = RightBorderSum; } /* 右边扫描结束 */ /* 下面返回"治"的结果 */ return Max3( MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum );}int MaxSubseqSum3( int List[], int N ){ /* 保持与前2种算法相同的函数接口 */ return DivideAndConquer( List, 0, N-1 );}
3.4 算法4:在线处理
“在线”的意思是指每输入一个数据就进行即时处理,在任何一个地方中止输入,算法都能正确给出当前的解。
- 数据结构-1 基本概念
- 数据结构(1)--基本概念
- 作业1 数据结构基本概念
- 第一章作业1-数据结构基本概念
- 数据结构基本概念
- 数据结构基本概念
- 数据结构基本概念
- 数据结构基本概念
- 数据结构--基本概念
- 数据结构基本概念
- 数据结构基本概念
- 【数据结构】基本概念
- 数据结构基本概念
- 数据结构基本概念
- 数据结构基本概念
- 数据结构基本概念
- 数据结构基本概念
- 数据结构基本概念
- kettle笔记
- Java增加校验位
- Android新布局ConstraintLayout的使用
- [BZOJ2303][APIO2011]方格染色 异或+并查集
- 浏览器开发之百度搜索url
- 数据结构-1 基本概念
- PHP判断某年的某月有多少天
- 在自绘CListCtrl控件中添加CSliderCtrl控件
- quick cocos 下实现ClippingNode(闪光特效/滑光特效。。。)
- 文章标题
- [BZOJ]2561 最小生成树 最小割
- div ul li 嵌套后解决高度自适应方法
- win10 uwp 反射
- 【Unity】封装SQLite管理类