# 数据结构第一周笔记(1)——基本概念(慕课浙大版本--XiaoYu)

456 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

数据结构定义

  1. 没有官方的定义,我选取慕课给出的3个定义中最通俗易懂的记录下来

  2. 数据结构(data structure)是计算机中存储,组织数据的方式。通常情况下,精心选择的数据结构可以带来最优效率的算法--中文维基百科

    三个例子

    1. 例1:如何在书架上摆放图书

    2. 二分查找:二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列

      1. 首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
    3. 例2:写程序实现一个函数PrintN,使得传入一个正整数为N的参数后,能顺序打印从1到N的全部正整数

//循环实现
void PrintN ( int N )
{
    int i;
    for( i=1 ;i<=N ;i++){
        printf("%d\n",i);
    }
    return;
}
​
//递归实现  弊端:递归的程序对空间的占用有的时候是很恐怖的
void PrintN ( int N )
{
    if( N ){
        printN( N - 1 );
        printf("%d\n",N);
    }
    return;
}
​
//解决问题方法的效率,也跟空间的利用效率有关
  1. 例3:写程序计算给定多项式在给定点x处的值

    image-20220626145149531

    //直接翻译的结构
    double f( 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 f( 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;
    }
    

    秦久邵的方法公式图

    image-20220626145709436

clock():捕捉从程序开始运行到clock()被调用时所耗费的时间。这个时间单位是clock tick,即"时钟打点"

常数CLK_TCK:机器时钟每秒所走的时钟打点数

//这套流程的模板
#include <stdio.h>
#include <time.h>clock_t start,stop;//clock_t是clock()函数返回的变量类型double duration;//记录被测函数的运行时间int main()
{//不在测试范围内的准备工作写在clock()调用之前
    start = clock();//开始计时
    MyFunction();//把被测函数加在这里
    stop = clock();//停止计时
    duration = ((double)(stop - start))/CLK_TCK;//计算时间
    //其他不在测试范围的处理写在后面,例如输出duration的值
    return 0;
}

image-20220626151549866

尝试计算这个图中的式子跑了多久

#include<stdio.h>
#include<time.h>
#include<math.h>
clock_t start,stop;
double duration;
#define ,MAXN 10 //多项式最大项数,即多项式阶数+1
double f1(int n , double a[] , double x);
double f2(int n , double a[] , double x);
​
int main()
{
    int i;
    double a[MAXN];//存储多项式的系数
    for (i = 0; i < MAXN; i++) a[i] = (double)i;
    
    //不在测试范围内的准备工作写在clock()调用之前
    start = clock();//开始计时
    f1(MAXN-1 , a , 1.1);//把被测函数加在这里
    stop = clock();//停止计时
    duration = ((double)(stop - start))/CLK_TCK;//计算时间
    //其他不在测试范围的处理写在后面,例如输出duration的值
    printf("ticks1 = %f\n",(double)(stop-start));
    printf("duration1 = %6.2e\n",duration);
    
    start = clock();//开始计时
    f2(MAXN-1 , a , 1.1);//把被测函数加在这里
    stop = clock();//停止计时
    duration = ((double)(stop - start))/CLK_TCK;//计算时间
    //其他不在测试范围的处理写在后面,例如输出duration的值
    printf("ticks1 = %f\n",(double)(stop-start));
    printf("duration2 = %6.2e\n",duration);
    
    
    return 0;
}
​
//跑出来结果都是0,因为运行太快了,clock函数捕捉不到它的区别
//解决方案:让被测函数重复运行充分多次,使得测出的总的时钟打点间隔充分长,最后计算被测函数平均每次运行的时间即可

以下是解决方案修改后的函数,只截取修改的部分

#define ,MAXK 1e7 //被测函数最大重复调用次数
double f1(int n , double a[] , double x);
double f2(int n , double a[] , double x);
​
int main()
{
    int i;
    double a[MAXN];//存储多项式的系数
    for (i = 0; i < MAXN; i++)//重复调用函数以获得充分多的时钟打点数 
        f1(MAXN-1,a,1.1);
    stop = clock();
    start = clock();//开始计时
    duration = ((double)(stop - start))/CLK_TCK/MAXK;//计算函数单词运行的时间
    //其他不在测试范围的处理写在后面,例如输出duration的值
    printf("ticks1 = %f\n",(double)(stop-start));
    printf("duration1 = %6.2e\n",duration);
    
    //以下第二个f2保持不变进行对比
    
    start = clock();//开始计时
    f2(MAXN-1 , a , 1.1);//把被测函数加在这里
    stop = clock();//停止计时
    duration = ((double)(stop - start))/CLK_TCK;//计算时间
    //其他不在测试范围的处理写在后面,例如输出duration的值
    printf("ticks1 = %f\n",(double)(stop-start));
    printf("duration2 = %6.2e\n",duration);
    
    
    return 0;
}

解决问题方法的效率,跟算法的巧妙程度有关