欢迎光临散文网 会员登陆 & 注册

1.1 什么是数据结构

2022-09-13 16:07 作者:Soap_mac_tavish  | 我要投稿

1.1.1 关于数据组织

1. 定义:没有官方定义。

非官方定义:“数据结构是数据对象,以及存在于该对象的实例和组成实例的数据元素之间的各种联系。这些联系可以通过定义相关的函数来给出。”

Sartaj Sahni,《数据结构、算法与应用》

“数据结构是ADT(抽象数据类型 Abstract Data Type)的物理实现。”

Clifford A.Shaffer,《数据结构与算法分析》

“数据结构(data structure)是计算机中存储、组织数据的方式。通常情况下,精心选择的数据结构可以带来最优效率的算法。”

中文维基百科

关键词:数据结构、算法

例1:如何在书架上摆放图书?这个问题不科学

该问题需要考虑:新书怎么插入?怎么找到某本指定的书?

方法1:随便放!

1. 新书怎么插入?哪儿有空放哪儿

2. 怎么找到某本指定的书?累死

方法2:按照书名的拼音字母顺序排放

1. 新书怎么插入?累死

2. 怎么找到某本指定的书?二分查找

方法3:把书架划分成几块区域,每块区域指定拜访某种类别的图书;在某种类别内,按照书名的拼音字母顺序排放。

1. 新书怎么插入?先定类别,二分查找确定位置,移出空位

2. 怎么找到某本指定的书?先定类别,再二分查找

问题:空间如何分配?类别应该分多细?

(答案未给出)

1.1.2 关于空间使用

例2:写程序实现一个函数PrintN,使得传入一个正整数为N的参数后,能顺序打印从1到N的全部正整数

方法1(循环实现,推荐):

void PrintN(int N) {

    int i;

    for (i = 1; i <= N; i++) {

        printf("%d\n", i);

    }

}

方法2(递归实现):

void PrintN(int N) {

    if (N) {

        PrintN(N – 1);

        printf("%d\n", N);

    }

}

当N很小时,运行一切正常,但当N比较大的时候,例如:N=100000时,程序直接没有输出,这是因为递归实现在这里占用空间过大导致的。所以解决问题方法的效率,也跟空间的利用效率是有关的。

例2 测试程序:

#include <stdio.h>

 

void PrintN(int N);

 

int main() {

    int n;

    scanf("%d", &n);

    PrintN(n);

    return 0;

}

 

附赠:例2的Python源码实现:

方法1(循环实现,推荐):

def PrintN(N):

    for i in range(1, n + 1):

        print(i)

方法2(递归实现):

def PrintN(N):

    if N:

        PrintN(N – 1)

        print(N)

例2测试程序(Python 3)

n = eval(input())

PrintN(n)

1.1.3 关于算法效率

例3:写程序计算给定多项式在给定点x处的值

多项式:f(x) = a0 + a1x + ... + an – 1xn – 1 + anxn

最傻最直接的算法:

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;

}

专业的程序员:

多项式定义:f(x) = a0 + x(a1 + x(...(an – 1 + x(an))...))

老祖宗:秦九韶

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;

}

知识点:C语言中clock():捕捉从程序开始运行到clock()被调用时所耗费的时间。这个时间单位是clock tick,即“时钟打点”。

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

常数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;

}

 

问题:如何测出不到1个tick的程序运行时间?

答案:重复

 

例3完整程序:

#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 = 1; i <= n; i++) {

        p += (a[i] * pow(x, i));

    }

    return p;

}

 

double f2(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;

}

 

int main() {

       int i;

       double a[MAXN];

       for (i = 0; i < MAXN; 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("%6.2e\n", duration);

       start = clock();

       for (i = 0; i < MAXK; i++) {

              f2(MAXN - 1, a, 1.1);

       }

       stop = clock();

       duration = ((double) (stop - start)) / CLK_TCK / MAXK;

       printf("%6.2e\n", duration);

       return 0;

}

 

本案例告诉我们:解决问题方法的效率,跟算法的巧妙程度有关。

 

Python代码:

最傻最直接的算法:

def f(n, a, x):

    p = a[0]

    for i in range(1, n + 1):

        p += (a[i] * pow(x, i))

    return p

专业的程序员:

def f(n, a, x):

    p = a[n];

    for i in range(1, n + 1):

        p = a[i - 1] + x * p

    return p

 

例3完整

import time as t

 

MAXN = 10

MAXK = 10000000

 

def f1(n, a, x):

    p = a[0]

    for i in range(1, n + 1):

        p += (a[i] * pow(x, i))

    return p

 

 

def f2(n, a, x):

    p = a[n];

    for i in range(n, 0, -1):

        p = a[i - 1] + x * p

    return p

 

 

 

a = [2, 3, 4, 5, 6, 7, 8, 10, 12, 16]  # 随便写的

start = t.time_ns()

for i in range(MAXK):

       f1(MAXN - 1, a, 1.1)

stop = t.time_ns()

duration = (stop - start) / MAXK

print(duration)

start = t.time_ns()

for i in range(MAXK):

       f2(MAXN - 1, a, 1.1)

stop = t.time_ns()

duration = (stop - start) / MAXK

print(duration)

1.1.4 抽象数据类型

所以:到底什么是数据结构?

数据对象在计算机中的组织方式

逻辑结构:树、图

物理存储结构

数据对象必定与一系列加载其上的操作相关联

完成这些操作所用的方法叫做算法

 

抽象数据类型(Abstract Data Type)

数据类型:数据对象集、数据集合相关联的操作集

抽象:描述数据类型的方法不依赖于具体实现

与存放数据的机器无关

与数据存储的物理结构无关

与实现操作的算法和编程语言均无关

只描述数据对象集和相关操作集“是什么”,并不涉及“如何做到”的问题。


1.1 什么是数据结构的评论 (共 条)

分享到微博请遵守国家法律