1、数据结构与算法 - 数据结构基础

数据结构与算法[基础]

程序 = 数据结构 + 算法。

数据结构就是指一组数据的存储结构。算法就是操作数据的一组方法

数据结构我们常见的如: 数组、栈、队列、哈希表、二叉树、图等等,而算法如: 排序算法、哈希算法、最短路径算法、字符串匹配算法等等。数据结构是为算法服务的,算法要作用在特定的数据结构之上。 因此,我们无法孤立数据结构来讲算法,也无法孤立算法来讲数据结构。


 大纲:

 数据结构核心名词解释
 逻辑结构与物理结构区别
 算法合计要求
 算法效率衡量方法
 算法时间复杂度
 算法空间复杂度计算

 

一、数据结构核心名词解释

 1、数据结构基本术语

数据
    程序的操作对象,用于描述客观事物。
    特点:1、具有可输入到计算机  2、可以被计算机处理
数据对象
    性质相同的数据元素的集合(类似于数组)
数据元素
    组成数据对象的基本单位
数据项
    一个数据元素由若干数据项组成
 
 也就是说多个数据项组成一个数据元素,多个数据元素的集合就是数据对象

 
 

如下就是一个数据元素:

 //声明一个结构体类型
 struct Teacher{     //一种数据结构
     char *name;     //数据项--名字
     char *title;    //数据项--职称
     int  age;       //数据项--年龄
 };
int main(int argc, const char * argv[]) {
     struct Teacher t1;     //数据元素;
     struct Teacher tArray[10]; //数据对象;

     t1.age = 18;       //数据项
     t1.name = "LJL";    //数据项
     t1.title = "平民";  //数据项
     return 0;
 }


 二、数据结构

 表述的是数据与数据之间的逻辑关系


 1、逻辑结构

 (1)、集合结构
    无序(没有先后顺序)。例如:字典、集合(NSSet)

 
 (2)、线性结构
    数据是一对一的结构,所有一对一的都是线性结构。存在唯一的第一个元素和唯一的最后一个元素
    例如:线性表、数组、栈、队列等
    队列 和 栈是特殊的线性结构。特殊在读取方式,队列FIFO先进先出,栈先进后出


 堆是链表结构
 
 (3)、树性结构
    一对多的关系,凡是一对多的数据关系都是树形结构。
 
 
 (4)、图形结构
    多对多的的关系
 
 
 2、物理结构
 数据最终是要存到内存中的,内存的存储方式只有两种
 1、顺序存储结构
    需要提前开辟一段联系的内存空间
    插入删除不方便,查找不方便


 2、链式存储结构
    不需要提前开辟连续空间
    插入删除方便,查找不方便


 
 数据结构不是单纯的用一种存储结构完成存储的


2、数据结构与算法的关系

(1)、算法

 定义:
 算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有序列,并且每个指令表示一个或多个操作。
 算法必须要有输入、输出和要求
 
 算法特性:
 输入输出      输入需要计算内容,输出结果
 有穷性         有限的执行次数和执行时间
 确定性         每一步的执行都是唯一的
 可行性         每次操作切实可行
 
 算法要求:
 正确性                                执行的结果必须准确
 可读性                                执行过程的可读性性要强便于查阅。注释、易懂
 健壮性                                对异常情况的处理。容错和抛出错误原因
 时间效率高和储存量低     执行的时间消耗要少,占用的空间资源要少。
 
算法有时间复杂度和空间复杂度
 1、为什么需要复杂度分析?
 因为传统的统计法受代码执行平台(宿主平台)和数据规模所限,所以需要一个无关的宿主平台,粗略的来估算算法执行效率的方法。
 2、什么是复杂度分析?
 复杂度分析分为时间复杂度分析和空间复杂度分析,使用大O表示法
 其中时间复杂度表示代码时间随数据规模增长的变化趋势,也称为渐进时间复杂度;
 同理,空间复杂度表示算法存储空间随数据规模增长的变化趋势,也称为渐进空间复杂度。
 3、怎么来做复杂度分析
 首先,时间复杂度分析有三个实用的方法,分别是
 只关心循环次数最多的一段代码
 加法法则:总复杂度等于量级最大的那段代码的复杂度
 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
 时间复杂度的量级分为两类
 多项类:O(1) O(log n) O(nlog n) O(m+n) O(m*n)
 非多项式:O(2的n次方) O(n!)
 而空间复杂度分析则简单一些,一般来说就是O(1)、O(n)、O(n的2次方)
 
 时间复杂度:
 包含

  1.  算法的输入时间
  2.  编译可执行代码
  3.  执行重复指令

 常见时间复杂度
 用大O表示法

  1.  用常数1 取代运行时间中所有常数 3->1 O(1);
  2.  在修改运行次数函数中,只保留最高阶项  n^3+2n^2+5 -> O(n^3)
  3.  如果在最高阶存在且不等于1,则去除这个项目相乘的常数  2n^3 -> O(n^3)

 时间复杂度常用术语:(大多数都是如下7种)

指数阶(不考虑)O(2^N)或者O(n!) 除非是非常小的n,否者会造成噩梦般的时间消耗,这是一种不切实际的算法时间复杂度,一般不考虑。
 时间复杂度的计算并不是让精确到每分每秒,所以通过大O表示法来计算大概的时间
 
 1. 常数阶时间复杂度计算 O(1)

//1+1+1 = 3 O(1)
    void testSum1(int n){
        int sum = 0;                //执行1次
        sum = (1+n)*n/2;            //执行1次
        printf("testSum1:%d\n",sum);//执行1次
    }
    
    //1+1+1+1+1+1+1 = 7 O(1)
    void testSum2(int n){
        int sum = 0;                //执行1次
        sum = (1+n)*n/2;            //执行1次
        sum = (1+n)*n/2;            //执行1次
        sum = (1+n)*n/2;            //执行1次
        sum = (1+n)*n/2;            //执行1次
        sum = (1+n)*n/2;            //执行1次
        printf("testSum2:%d\n",sum);//执行1次
    }
 
    //x=x+1; 执行1次
    void add(int x){
        x = x+1;
    }

2.线性阶时间复杂度

    //(n+1)+n; 执行n次 O(n)
    void add2(int x,int n){
        for (int i = 0; i < n; i++) {   //执行n+1 次
            x = x+1;                    //执行n次
        }
    }
    
    //1+(n+1)+n+1 = 3+2n -> O(n)
    void testSum3(int n){
        int i,sum = 0;               //执行1次
        for (i = 1; i <= n; i++) {   //执行n+1次
            sum += i;                //执行n次
        }
        printf("testSum3:%d\n",sum);  //执行1次
    }

3.对数阶
2的x次方等于n x = log2n  ->O(log n)。大O表示法会把2省略掉
O(log n) 其实也也就是下图的 K。由于输入的问题具体的log2n 见下图

    void testA(int n){
        int count = 1;         //执行1次
        //n = 10
        while (count < n) {
            count = count * 2;
        }
    }

4.平方阶

    //x=x+1; 执行n*n次 ->O(n^2)
    void add3(int x,int n){
        for (int i = 0; i< n; i++) {
            for (int j = 0; j < n ; j++) {
                x=x+1;
            }
        }
    }

    //n+(n-1)+(n-2)+...+1 = n(n-1)/2 = n^2/2 + n/2 = O(n^2)
    //sn = n(a1+an)/2
    void testSum4(int n){
        int sum = 0;
        for(int i = 0; i < n;i++)
            for (int j = i; j < n; j++) {
                sum += j;
            }
        printf("textSum4:%d",sum);
    }
    
    //1+(n+1)+n(n+1)+n^2+n^2 = 2+3n^2+2n -> O(n^2)
    void testSum5(int n){
        int i,j,x=0,sum = 0;           //执行1次
        for (i = 1; i <= n; i++) {     //执行n+1次
            for (j = 1; j <= n; j++) { //执行n(n+1)
                x++;                   //执行n*n次
                sum = sum + x;         //执行n*n次
            }
        }
        printf("testSum5:%d\n",sum);
    }

5.立方阶

    //1+n+n^2+n^3+n^3 = 1+n+n^2+2n^3 -> O(n^3)
    void testB(int n){
        int sum = 1;                         //执行1次
        for (int i = 0; i < n; i++) {        //执行n次
            for (int j = 0 ; j < n; j++) {   //执行n*n次
                for (int k = 0; k < n; k++) {//执行n*n*n次
                    sum = sum * 2;          //执行n*n*n次
                }
            }
        }
    }

空间复杂度
算法的空间复杂度通过计算算法所需的存储空间实现,算法空间复杂度的计算公式记做:
 S(n)=n(f(n))
 其中n为问题的规模,f(n)为语句关于n所占存储空间的函数。
 程序空间计算因素:

  1.     寄存本身的指令
  2.     常数
  3.     变量
  4.     输入
  5.     对数据进行操作的辅助空间

 在考量算法的空间复杂度,主要考虑算法执行时所需要的辅助空间
 空间复杂度计算:
 问题:数组逆序,将一维数组a中的n个数逆序存放在原数组中
 

int main(int argc, const char * argv[]) {
    printf("Hello, World!\n");
 
    int n = 5;  //这是临时变量不是辅助空间
    int a[10] = {1,2,3,4,5,6,7,8,9,10};
 
    //1、算法实现(1)
    //使用了一个赋值空间,常数阶 空间复杂度是O(1)   O(1)
    int temp; //这是辅助空间。这里就算多写几个 temp 一样是 O(1),这是常数阶
    for(int i = 0; i < n/2 ; i++){
        temp = a[i];
        a[i] = a[n-i-1];
        a[n-i-1] = temp;
    }
 
    for(int i = 0;i < 10;i++){
        printf("%d\n",a[i]);
    }


    //2、算法实现(2)
    //这个是有 n 个数组,所以就是 O(n)
    int b[10] = {0};
    for(int i = 0; i < n;i++){
        b[i] = a[n-i-1];
    }
    for(int i = 0; i < n; i++){
        a[i] = b[i];
    }
    for(int i = 0;i < 10;i++){
        printf("%d\n",a[i]);
    }
    
    return 0;
}

算空间复杂度算的是辅助空间
 
 算法好坏的衡量
 衡量算法的时候衡量的是最坏的情况,如果最坏的情况一样就衡量平均情况

 

总结:

主要是一些基本该你,总结是针对本人的总结。如果都比较熟悉可以忽略下面的内容。

1、数据结构

数据
    程序的操作对象,用于描述客观事物。
    特点:1、具有可输入到计算机  2、可以被计算机处理
数据对象
    性质相同给的数据元素的集合(类似于数组)
数据元素
    组成数据对象的基本单位
数据项
    一个数据元素由若干数据项组成

2、大O表示法

  1.  用常数1 取代运行时间中所有常数 3->1 O(1);
  2.  在修改运行次数函数中,只保留最高阶项  n^3+2n^2+5 -> O(n^3)
  3.  如果在最高阶存在且不等于1,则去除这个项目相乘的常数  2n^3 -> O(n^3)

3、

发布了104 篇原创文章 · 获赞 13 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/shengdaVolleyball/article/details/105247121