数据结构第一天
到底什么是数据结构?
答:数据对象必须与一系列加在其上的操作相关联
完成这些操作所用的方法就是算法
除此之外呢,还有就是逻辑结构和计算机内部的物理存储结构(数组or链表)
抽象数据类型
数据类型:数据对象集合,数据集合相关联的操作集(C语言中独立处理,java和C++是封装在一个类中的)
抽象:描述数据类型的方法不具体实现,1.与存放数据的机器无关 2.与数据存储的物理结构无关 3.与实现操作的算法和编程语言均无关,只需要知道它是什么,而不具体去实现 ,比如矩阵的抽象数据类型定义。
eg1:写程序实现一个函数printN,使得传入一个正整数为N的参数后,能顺序打印从1到N的全部整数。
//一般实现
int printN(int N){
int i;
for(i=1;i<N;i++){
printf("%d\n",N);
}
return ;
}
//递归实现
int printN(int N){
if(N){
printf(N-1);
printf("%d\n",N);
}
return ;
}
//测试
#include<stdio.h>
void printN(int N);
int main(){
int N;
scanf("%d",&N);
printfN(N);
return 0;
}
eg2:写程序计算给定多项式在定点x处的值f(x)=a0+a1x+…+an-1Xn-1+an*Xn;
//数学思维 从外到内
int printN(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;
}
}
//秦九韶算法 从内到外
int printN(int n,double a[],double x){
int i;
double p=a[N];
for(i=N;i>0;i--){
p+=a[i-1]+x*p;
return p;
}
}
测试两个函数的程序运行时间
#include<stdio.h>
#include<time.h>
#include<math.h>
#define MAXN 10000
clock_t start,stop;
clock_t start1,stop1;
double duration,duration1;
double printN1(int n,double a[],double x);
double printN2(int n,double a[],double x);
int main(){
int i;
double a[MAXN];
printN1(MAXN-1,a,1.1);
start=clock();
printN1(MAXN-1,a,1.1);
stop=clock();
start1=clock();
printN2(MAXN-1,a,1.1);
stop1=clock();
duration=(double)(stop-start)/CLK_TCK;
duration1=(double)(stop1-start1)/CLK_TCK;
printf("%lf\n%lf",duration,duration1);
return 0;
}
double printN1(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 printN2(int n,double a[],double x){
int i;
double p=a[n];
for(i=n;i>0;i--){
p+=a[i-1]+x*p;
return p;
}
}
给定N个整数的序列{A1,A2,…An},求最大子列和(算法)
int MaxSubseqSum1( int A[], int N )
{ int ThisSum, MaxSum = 0;
int i, j, k;
for( i = 0; i < N; i++ ) { /* i是子列左端位置 */
for( j = i; j < N; j++ ) { /* j是子列右端位置 */
ThisSum = 0; /* ThisSum是从A[i]到A[j]的子列和 */
for( k = i; k <= j; k++ )
ThisSum += A[k];
if( ThisSum > MaxSum ) /* 如果刚得到的这个子列和更大 */
MaxSum = ThisSum; /* 则更新结果 */
} /* j循环结束 */
} /* i循环结束 */
return MaxSum;
}
减少时间复杂度后的算法(O(n3)—>O(n2))
int MaxSubseqSum2( int A[], int N )
{ int ThisSum, MaxSum = 0;
int i, j;
for( i = 0; i < N; i++ ) { /* i是子列左端位置 */
ThisSum = 0; /* ThisSum是从A[i]到A[j]的子列和 */
for( j = i; j < N; j++ ) { /* j是子列右端位置 */
ThisSum += A[j]; /*对于相同的i,不同的j,只要在j-1次循环的基础上累加1项即可*/
if( ThisSum > MaxSum ) /* 如果刚得到的这个子列和更大 */
MaxSum = ThisSum; /* 则更新结果 */
} /* j循环结束 */
} /* i循环结束 */
return MaxSum;
}
给定N个整数的序列{A1,A2,…An},求最大子列和(分而治之)
#include<stdio.h>
int Max3(int A,int B,int C)//求三个数中的最大值
{
return A>B?A>C?A:C:B>C?B:C;
}
int DivideAndConquer(int List[],int left,int right)//分治策略
{
int MaxLeft,MaxRight;
int MaxLeftSum,MaxRightSum;
int LeftSum,RightSum;
int center,i;
if(left==right)//递归的终止条件
if(List[left]>0) return List[left];
else return 0;
center=(left+right)/2; //分
MaxLeft=DivideAndConquer(List,left,center);//求左边的最大值
MaxRight=DivideAndConquer(List,center+1,right);//求右边的最大值
MaxLeftSum=0;LeftSum=0;//从中间开始往两边求
for(i=center;i>=left;i--){
LeftSum=LeftSum+List[i];
if(LeftSum>MaxLeftSum) //从中间往左边扫描
MaxLeftSum=LeftSum;
}
MaxRightSum=0;RightSum=0;
for(i=center+1;i<=right;i++){
RightSum=RightSum+List[i];
if(RightSum>MaxRightSum) //从中间往右边扫描
MaxRightSum=RightSum;
}
return Max3(MaxLeft,MaxRight,MaxLeftSum+MaxRightSum);//将三个结果合在一起选取最大值
}
int MaxSubseqSum3(int List[],int N)//把借口转换过去
{
return DivideAndConquer(List,0,N-1);
}
int main()
{
int subsque[100000],n,j;//输入n个随机的数
scanf("%d",&n);/*首先输入数的个数*/
for(j=0;j<n;j++)
scanf("%d",&subsque[j]);
printf("%d",MaxSubseqSum3(subsque,n));
return 0;
}