【数据结构】一.绪论

1.什么是数据结构?

(1)五个基本概念:

数据:能被输入进电脑进行处理的所有信息符号的总称,包括文字,声音,图片视频等等;

数据项:数据的最小单位

数据元素:数据的基本单位 ;一个数据元素可以由若干个数据项组成; 比如:一条书目的信息为                     一个数据元素,而其中书的价格,作者,出版社等信息就是一个个数据项

数据对象:性质相同的数据元素的集合比如在一个数组中,每一个元素都是数据元素,而一整                       个数组是一个数据对象

数据结构:存在特定关系的数据元素的集合

                 相当于是数据元素的容器,定义了它如何存储如何操作,强调数据的组织和管理方式

数据项 数据元素 数据对象 数据结构都可以被称为数据


(2)数据结构包含的内容

      前面说到数据结构定义了数据如何进行存储和操作,存储又涉及到逻辑结构和存储结构

(1 逻辑结构

   逻辑结构就是将数据间的关系抽象成可视化的数学模型,体现数据元素之间的组织方式。我们具体会学四种逻辑结构:

线性:
    线性结构(Linear)

     特点: 一对一,有一个确定的头和一个确定的尾  

     例子: 学生成绩单

非线性:
    树形结构(Tree)

    特点: 一对多

    例子: 文件系统的目录结构,下棋时对应的很多种局势

    图状结构/网状结构(Graph)

    特点:多对多

    例子:  人物关系图,地铁路线图

    集合(Set)

    特点:和我们高中数学学的集合是一样的,就是一个单纯的包含关系

(2存储结构

 在计算机中,将数据元素实际地存进计算机有两种方法: 顺序映像链式映像

 对应的两种存储结构分为 顺序存储链式存储

顺序映像和顺序存储

顺序映像就是将数据在计算机中用连续的地址来存储数据,使我们可以通过索引来访问数据

最简单直接的例子就是数组

特点:逻辑结构上相邻的位置物理结构上也相邻

优点: 存取元素效率高

缺点: 插入和删除时会引起大量元素移动 

应用: 线性表

其实顺序映像和顺序存储这两个概念很像 

顺序映像强调的是逻辑上数据之间的顺序关系,而顺序存储强调的是物理存储的布局;

一句话概括就是 顺序映像通过顺序存储进行实现

链式映像和链式存储

链式映像是随机的在计算机中取没有被占用的内存单元存储元素,所以数据的地址是不连续的,需要通过指针来进行连接

优点: 插入删除元素很方便;

缺点:访问元素效率低(不能直接实现随机访问,必须要通过指针进行遍历)

应用:线性表,树,图

(3)操作

指对数据施加的操作 如查找,插入,删除,排序,修改等。

这些操作涉及到算法,而算法的设计主要依赖于数据的逻辑结构,算法的实现主要依赖于数据的存储结构


2.算法

(1)什么是算法?

对一个具体问题解决方法步骤的描述

 (2)特点

 有穷性,确定性,可行性,输入,输出;

(3)好的算法的要求

正确: 不仅是不含语法错误,而且无论输入什么都可以偶的符合要求的结果;

可读: 要写注释;

健壮性: 有容错;

效率和低存储: 执行时间短,占用内存;

(4)算法的效率

 评估算法的效率 通常从 时间复杂度空间复杂度 两个维度进行考量

(1 时间复杂度

  标准: 以基本语句的执行次数为基本的度量单位

  体现算法执行时间和问题规模(算法输入的数据量的大小,用n来表示)之间的关系,用O来表示

  计算时间复杂度时,我们通常只看执行频度最高的语句(一般是循环语句)来确定

  时间复杂度的表达式为O(f(n))通常f(n)不需要是一个具体的函数表达式,只要能表达增长率即可(n,n^{2},\log n...)

(2 空间复杂度

若问题规模只与问题本身有关,而与算法无关,则只考虑算法占用的额外空间(即不考虑输入数据需要占的内存),表达方式与时间复杂度相同

  来看几个例子:

   a.线性查找

#include <stdio.h>

int linearSearch(int arr[], int n, int key) {
    for (int i = 0; i < n; i++) {
        if (arr[i] == key) {
            return i; // 找到元素,返回索引
        }
    }
    return -1; // 未找到
}

时间复杂度:最好情况下,循环执行一次就return了,但是我们要考虑最坏情况

在最坏情况下,循环要执行n次,时间复杂度为O(n);

空间复杂度: 这个算法并没有使用额外的变量去储存数据,所以空间复杂度为O(1)

b.二分查找

int binarySearch(int arr[], int n, int key) {
    int left = 0, right = n - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (arr[mid] == key) {
            return mid; // 找到元素,返回索引
        } else if (arr[mid] < key) {
            left = mid + 1; // 在右半边查找
        } else {
            right = mid - 1; // 在左半边查找
        }
    }
    return -1; // 未找到
}

时间复杂度

同样分析最坏情况 每循环一次 数据范围就缩小一半

比如: 问题规模为100,第一次循环结束后是50-100(数据范围为100/2),第二次循环结束之后是75-100 (数据范围为100/2^2)。。。

最后当left == right时 循环结束 此时只剩下一个元素 假设一共循环了k次,则 n/2^k = 1

则 k = log₂(n)  

时间复杂度为O(\log n)

空间复杂度:

只使用了几个局部变量right,left,mid,它们占用的空间与问题规模无关,空间复杂度为O(1)

(c)冒泡排序

void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                // 交换元素
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

时间复杂度:重点关注循环体:当i = 0 时,内部循环n-1次, i = 1 时,内部循环n - 2次,所以一共是 (n-1)+(n-2)+(n-3)+....+1 = n(n-1)/2

时间复杂度为O(n^2)

空间复杂度: 同二分查找,为O(1)

(4)最简单的!

x = 0; 
y = 0;
while(x<100)
{
      y += x;
      x++;
}

语句执行次数与问题规模显然无关,时间复杂度为O(1)--常数阶 空间复杂度也为O(1)

(5)将一个字符串在另一个字符串中出现的相同字符删除(这个比较复杂)

int found(char *t, char *c)  //在字符串t中寻找与字符c相同的字符
{while(*t&&*t!=*c) t++; //遍历字符串t,找到相同的字符返回,若没有找到返回空
return *t;
}

void delchar(char *s, char *t)  //删除字符串s中和t字符串中相同的字符
{ char *p,*q; 	
   p=s;
   while(*p)   //遍历字符串s
      if(found(t,*p))  //s中的字符是否在字符串t中出现
      {q=p; //如果找到了,逐个字符向前拷贝
        while(*q) *q++=*(q+1);   
        } else p++;

}

时间复杂度:

设字符串t 长度为n; 字符串s长度为m;

对于外层循环,最坏情况下下循环s字符中的每个字符,共m次;在调用found函数时,最坏情况下要循环t中的每个字符,共n次;在删除字符将后面的字符逐个往前拷贝的循环中,最坏情况下要如果被删除的是第一个字符,第二个字符要移动m-1次,第三个字符要移动m-2次… m-1+m-2+m-3+…1=m*(m-1)/2 字符移动操作的时间复杂度为O(m^2)

所以总的时间复杂度O(n*m + m^2);

设字符串t 长度为n; 字符串s长度为m;

对于外层循环,最坏情况下下循环s字符中的每个字符,共m次;在调用found函数时,最坏情况下要循环t中的每个字符,共n次;在删除字符将后面的字符逐个往前拷贝的循环中,最坏情况下要如果被删除的是第一个字符,第二个字符要移动m-1次,第三个字符要移动m-2次… m-1+m-2+m-3+…1=m*(m-1)/2 字符移动操作的时间复杂度为O(m^2)

所以总的时间复杂度O(n*m + m^2);

空间复杂度:同二分查找,为O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值