数据结构与算法
作者:互联网
数据结构与算法
关于数据结构组织-例_图书的摆放
一、定义:数据结构是数据对象,以及存在于该对象的实例和组成实例的数据元素之间的各种联系。这些联系可以通过定义的函数来给出。(定义并不唯一)
二、对定义的解释(举例)
1、如何在书架上摆放图书?
<1>新书怎么插入?
<2>怎么找到某本指定的书?
方法1:随便放
方便新书插入,但极不方便找到某本指定的书。
方法2:按照书名的拼音字母顺序排放
用二分查找法查找指定的书,方便查找但不方便新书插入。
方法3:把书架划分成几块区域,每块区域指定摆放某种类别的图书;在每种类别内,按照书名拼音字母顺序排放
操作1:新书怎么插入?
先定类别,二分查找确定位置,移出空位
操作2:怎么找到某本指定的书?
先定类别,再二分法查找
问题:空间的分配及类别的分类
总结:解决问题方法的效率和数据的组织方式有关
关于空间使用-例_PrintN函数的实现
例子:写程序实现一个函数printN,使得传入一个正整数为N的参数后,能顺序打印从1到N的全部正整数
循环实现
vido PrintN(int N)
{
int i;
for(i=1;i<=N;i++)
printf("%d",N);
return;
}
递归实现
vido PrintN(int N)
{if(N)
{
PrintN(N-1)
printf("%d",N);
}
return;
}
当N=1000000时,递归方法无法实现;
总结:解决问题方法的效率,跟空间的利用效率有关。
关于算法效率
例子:写程序计算给定多项式在给定点x的值
方法一:
double f(int n,double a[],double x)
{
int i;
double p=a[0];
for(i=1;i<=n;i++)
p+=(a[i]*pow(x,i));
return p;
}
方法二:
double f(int n,double a[],double x)
{
int i;
double p=a[i];
for(i=n;i>0;i--)
{
p=a[i-1]+x*p;
}
return p;
}
相关知识:函数pow(x,y)即数学函数,x的y次方;
clock():捕捉从程序开始运行到clock()被调用时所耗费的时间。这个时间单位是clock tick,即“时钟打点”
常数CLK_TCK:机器时钟每秒所走的时钟打点数。
计算程序时间的代码
#include<stdio.h>
#include<time.h>
#include<math.h>
clock_t start ,stop;
double duration;
#define MAXN 10
#define MAXK 1e7
double f1(int n ,double a[],double x)
{
int i;
double p=a[0];
for(i=0;i<=n;i++)
p+=(a[i]*pow(x,i));
return p;
}
double f2(int n,double a[],double x)
{
int i;
double p=a[i];
for(i=n;i>=0;i--)
p=a[i-1]+x*p;
return p;
}
int main()
{
int i;
double a[MAXN];
for(i=0;i<MAXK;i++)a[i]=(double)i;
start=clock();
for(i=0;i<MAXK;i++)
f1(MAXN-1,a,1.1);
stop=clock();
duration=(double)(stop-start)/CLK_TCK/MAXK;
printf("tickes=%f\n",(double)(stop-start));
printf("duration1=%6.2e\n",duration);
for(i=0;i<MAXK;i++)a[i]=(double)i;
start=clock();
for(i=0;i<MAXK;i++)
f2(MAXN-1,a,1.1);
stop=clock();
duration=(double)(stop-start)/CLK_TCK/MAXK;
printf("tickes=%f\n",(double)(stop-start));
printf("duration2=%6.2e\n",duration);
return 0;
}
运行结果如下:
总结:解决问题方法的效率与算法的巧妙有关。
抽象数据类型
一、所以到底什么是数据结构
1、数据对象在计算机的中的组织方式
- 逻辑结构(一对一,一对多,多对多)
- 物理存储结构(计算机如何存储数据)
2、数据对象必定与一系列加在其上的操作相关联
3、完成这些操作所用的方法就是算法
二、抽象数据类型(Abstract Data Type)
1、数据类型
<1>数据对象集(是什么东西)
<2>数据集合相关联的操作集(对数据的操作)
2、抽象:描述数据类型的方法并不依赖于具体实现
<1>与存放数据的机器无关
<2>与数据存储的物理结构无关
<3>与实现操作的算法和编程语言均无关
也就是说只描述对象集和相关操作集“是什么”,并不涉及“如何做到”的问题。
算法
一、定义:
1、一个有限指令集
2、接受一些输入(有些情况下不需要输入)
3、必须产生输入
4、一定在有限步骤之后终止
5、每一条指令必须:
- 有充分明确的目标,不可以有歧义;
- 计算机能处理的范围之内
- 描述应不依赖于任何一种计算机语言以及具体的实现手段
二、什么是好的算法
1、空间复杂度S(n)——根据算法写成的程序在执行时占用存储单元的长度。这个长度往往与输入数据的规模有关。空间复杂度过高的算法可能导致使用的内存超限,造成程序非正常中断
2、时间复杂度T(n)——根据算法写成的程序在执行时耗费时间长度。这个长度往往也与输入数据的规模有关。时间复杂度过高的低效算法可能导致我们在有生之年都等不到结果
3、在分析一般算法的效率时,我们经常关注下面两种复杂度
<1>最坏情况复杂度
<2>平均复杂度
分析时常分析最坏情况复杂度
4、复杂度的渐进表示法
分析时,竭尽所能寻找最大的下届和最小的上界。
总结:1、若两段算法分别有复杂度T1(n)=O(f1(n))和T2(n)=O(f2(n)),则
<1>T1(n)+T2(n)=max(O(f1(n)),O(f2(n)))
<2>T1(n)*T2(n)=O(f1(n)*f2(n))
2、若T(n)是关于n的k阶多项式,那么T(n)=Θ(n的k次方)
3、一个for循环的时间复杂度等于循环次数乘以循环体代码的复杂度
4、if—else结构的复杂度取决于if的条件判断复杂度和两个分支的复杂度,总体复杂度取三者最大
例题:
算法1:
int MaxSubseqsum1(int A[],int N)
{
int ThisSum,MaxSum=0;
for(i=0;i<N;i++)
{
for(j=i;j<N;j++)
{
ThisSum=0;
for(k=i;k<=j;k++)
ThisSum+=A[k];
if(ThisSum>MaxSum)
MaxSum=ThisSum;
}
}
return MaxSum;
}
算法2:
int MaxSubseqSum1(int A[],int N)
{
int i,j;
for(i=0;i<n;i++)
ThisSum=0;
for(j=i;j<N;j++)
{
ThisSum+=A[j];
if(ThisSum>MaxSum)
MaxSum=ThisSum;
}
return MaxSum;
}
算法2要比算法1简单。
算法三(在线算法):
int MaxSubseqSum4(int A[],int N)
int ThisSum,MaxSum;
int i;
ThisSum=MaxSum=0;
for(i=0;i<N;i++)
{
ThisSum+=A[i];
if(ThisSum>MaxSum)
else if(ThisSum<0)
ThisSum=0;}
return MaxSum;
引子_多项式表示
一、线性表及其实现
1、线性结构的定义:数据元素之间构成一个有序的序列
例子:
方法1:采用顺序存储结构直接表示一元多项式
缺点:如果要表示x+pow(x,3000),就必须采用一个大小至少为3001的数组,而在这个数据中大多数数据均为0,只有两项不为0,显然空间浪费得厉害。
方法二:顺序存储结构表示非零项:
按指数大小有序排列
方法三:链表结构存储非零项
启示:
<1>同一个问题可以有不同的表示(存储)方法
<2>有一类共性问题:有序线性序列的组织和管理
2、什么是线性表
<1>定义:由同类型数据元素构成有序序列的线性结构
<2>特点:
1)表中元素个数被称为线性表长度
2)线性表没有元素时,称为空表
3)表起始位置称表头,表结束位置称表尾
typedef strcut LNode *List
strcut LNode{
ElementType Data[MAXSIZE];
int Last;
};
struct LNode L;
List PtrL;
访问下标为i的元素:L.Data[i]或PtrL->Data[i]
线性表的长度:L.Last+1或PtrL->Last+1
主要操作的实现
1.初始化(建立空的顺序表)
List MakeEmpty()
{List PtrL;
PtrL=(List)malloc(sizeof(struct LNode));
PtrL->=-1;
return PtrL;}
2.查找
int Find(ElementType X,List PtrL)
{int i=0;
while(i<=PtrL->Last&&PtrL->Data[i]!=X)
i++;
if(i>PtrL->Last)
return -1;
else return i;}
3.插入(第i(1<=i<=n+1))个位置上插入一个值为X的新元素)
void Insert(ElementType X,int,List PtrL)
{
if(PtrL->Last==MAXSIZE-1)
{printf("表满");
return;
}
if(i<1||i>PtrL>Last+2)
{printf("位置不合法");
return;
}
for(j=PtrL->Last;j>=i-1;j--)
PtrL->Data[j+1]=PtrL->Data[j];
PtrL->Data[i-1]=X;
PtrL->Last++;
return;
}
平均移动次数为n/2
平均时间性能为O(n)
4.删除(删除表的第i(1<=i<=n)个位置上的元素)
void Delete(int i,List PtrL)
{int j;
if(i<1||i>PtrL->Last+1){
printf("不存在第%d个元素",i);
return;
}
for(j=i;j<=PtrL->Last;j++)
PtrL->Data[j-1]=PtrL-->Data[j];
PtrL->Last--;
}
标签:return,int,double,复杂度,PtrL,算法,数据结构 来源: https://blog.csdn.net/weixin_53549425/article/details/113737757