数据结构第一章

1.1 数据结构相关概念

1.1.1 为什么要学习数据结构

为什么要学习数据机构?在回答这个问题之前,我们是不是应该弄清楚什么是数据结构,数据结构能够用来做什么?最直白的,它能够帮我们解决什么问题?

我们之前的学习的设计模式和现在的数据结构,有个相似的特点,他们两个都是在思想层面的东西,和具体的语言无关,你可以用其他的语言去实现这些思想都没有问题。

设计模式在教我们如何编写代码,让我们的代码更具有可扩展性、灵活性、可复用性,这个是编码层面上的,那么数据结构呢?我们举一个例子:

比如我们c语言中没有数组这么个数据结构,那么你如何实现10个数排序呢? 是不是要定义10个变量,然后让10个变量互相比较,重复劳动,但是你用数组之后,是不是问题变得简单,只需要通过数组下标就可以,提高了程序的编码效率。

再比如说,我们有了数组了,为什么还需要学习链表这种数据结构?数组是连续内存空间,一旦定义了不能改变,适应性差,但是链表你有多少数据,我就创建多少个结点,而且比如说数据,你删除中间位置一个元素,会引起后面数据的移动,但是链表不会啊,在有些场合下,你使用链表是不是会增加程序的效率。

从我们讲的东西中,也可以得出数据结构的概念,数据结构就是帮我们解决如何组织和存储数据的方式。

数据结构主要研究非数值计算问题的程序中的操作对象以及他们之间的关系,不是研究复杂的算法

 数据结构是计算机存储、组织数组的方式

1.1.2 数据结构中的基本概念

数据 - 程序的操作对象, 用于描述客观事物

数据是一个抽象的概念,将其进行分类后得到的程序设计语言中的类型,如:int,float,char等等

数据元素:组成数据的基本单位。

数据项:一个数据元素由若干数据项组成

数据对象:性质相同的数据元素的集合(比如:数组,链表)。

 //声明一个结构体类型
 struct _MyTeacher//一种数据类型
 {
 char name[32];
     char tile[32];
     int age;
     char addr[128];
 };
 ​
 int main()
     
 {
     struct _MyTeacher t1;//数据元素
     struct _MyTeacher tArray[30];//数据对象
     memset(&t1,0,sizeof(t1));
     
     strcpy(t1.name,"name");//数据项
     strcpy(t1.addr,"addr");//数据项
     strcpy(t1.tile,"addr");//数据项
     t1.age=1;
 }

1.2.1 算法的概念

为啥子我们学习数据结构还要了解算法?

     比如说:我有10个学生,我们将10个学生保存在一个链表中,但是我不能把学生保存进去就完事了,我放进去是为了使用这些个数据完成一定的业务需求,比如按成绩大小排序并显示,比如计算这些学生的平均分等等,这些才是我们最终要解决的问题,既然要解决问题,那么就需要一些算法,比如排序算法,比如计算平均分的算法,对吧?所以数据结构和算法是互相配合完成工作。

算法是特定问题求解步骤的描述,在计算机中表现为指令的有限序列,算法是独立存在的一种解决问题的方法和思想。

     对于算法而言,语言并不重要,重要的是思想。

1.2.2 算法和数据结构区别

数据结构只是静态的描述了数据元素之间的关系,高效的程序需要在数据结构的基础上设计和算法选择。

  • 算法是为了解决实际问题而设计的

  • 数据结构是算法需要处理的问题载体

  • 数据结构与算法相辅相成

1.2.3 算法特性

  • 输入:算法具有0个或多个输入

  • 输出:算法至少由1个或多个输出

  • 有穷性:算法在有限的步骤之后会自动结束而不会无限循环,并且每一个步骤在接收的实际内完成

  • 确定性:算法中的每一步都有确定的含义,不会出现二义性

  • 可行性:算法的每一步都是可行的,也就是说每一步都能够执行有限的次数完成。

问题: 针对某一具体问题,解决此问题的算法是唯一的吗?

比如说:求从1到100的和?

 #define _CRT_SECURE_NO_WARNINGS
 #include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
 //算法1
 long sum1(int n)
 {
 long ret = 0;
     int * array=(int *)malloc(n*sizeof(int));
     int i=0;
     for(int i=0;i<n;i++)
     {
         array[i]=i+1;
     }
     for(int i=0;i<n;i++)
     {
 ret+=array[i];
     }
     free(array);
     return ret;
 }
 ​
 //算法2
 long sum2(int n)
 {
 long ret =0;
     int i=0;
     for(i=1;i<=n;i++)
     {
 ret+=i;
     }
     return ret;
 }
 ​
 //算法3
 long sum3(int n)
 {
 long ret = 0;//1
    if(n>0)
    {
 ret=(1+n)*n/2;
    }
  return ret;
 }
 ​
 int main()
 {
 print("%d",sum1(100));
     print("%d",sum2(100));
     print("%d",sum3(100));
     system("pause");
     return EXIT_SUCCESS;
 }

同样一个问题,我有三种不同的算法,这三种算法都可以解决同样的问题,那么我们如何选择?需要有个方法来衡量算法的效率。

1.2.4 算法效率的度量

1.2.4.1 事后统计法

主要通过设计好的测试程序和数据,利用计算机的计时器对不同算法的编制的程序的运行时间进行比较,从而确定算法效率的高低。

  • 统计方法

比较不同算法对同一组输入数据的运行处理时间

  • 缺陷

    • 为了获得不同算法的运行时间必须编写相应程序

    • 运行时间严重依赖硬件以及运行时的环境因素

    • 算法的测试数据的选取相当困难

  • 总结:

    • 事后统计虽然直观,但是实施困难且缺陷多

1.2.4.2 事前分析估算

在计算机程序编制前,依据统计方法对算法进行估算

  • 统计方法:

    • 依据统计的方法对运算效率进行估算

  • 影响算法效率的主要因素:

    • 算法采用的策略和方法

    • 问题的输入规模

    • 编译器所产生的代码

    • 计算机执行速度

算法推导的理论基础:

  • 算法最终编译成具体的计算机指令

  • 每一个指令,在具体的计算机上运行速度固定

  • 通过具体的步骤,就可以推导出算法的复杂度(如下表)

次数算法C(4n+8)算法C1(n)算法D(2n2+1)算法D1 (n2)
n=112131
n=216294
n=3203199
n=104810201100
n=1004081002000110000
n=10004008100020000011000000
次数算法G(2n2)算法H(3n+1)算法I(2n2+3n+1)
n=1246
n=28715
n=5501666
n=1020031231
n=1002000030120301
n=1000200000030012003001
n=1000020000000030000120000300001
n=1000002000000000030000012000003000001

怎么判断一个算法的效率?(规则如下)

  • 判断一个算法的效率时,往往只需要关注操作数量的最高此项,其次要项和常数项可以忽略

  • 在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度

  • 只有常数项记作1

  • 操作数量的估算可以作为时间复杂度的估算

1.2.4.3 大O表示法

  • 算法的时间复杂度

    • 常见的时间复杂度

执行次数函数非正式术语
12O(1)常数阶
2n+3O(n)线性阶
3n2+2n+1O(n2)平方阶
5log2n+20O(logn)对数阶
2n+3nlog2n+19O(nlogn)nlogn阶
6n3+2n2+3n+4O(n3)立方阶
2nO(2n)指数阶

总结:

  • 只关注最高此项

  • 时间复杂度是指最坏时间复杂度

  • 只有常数项记作1

  • 算法的空间复杂度

算法的空间复杂度并不是计算所有算法所占的空间,而是使用的辅助空间的大小

1.2.4.4 大O表示法练习题

语句的执行次数

while(count<n)

{

count=count*2

}

上面的复杂度为O(logn)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值