数据结构学习

文章目录

  • 数据结构的概述
  • 数据和数据之间的关系
  • 一、线性关系
    • 特点
    • 数组
    • 链表
    • 队列
  • 二、树关系
  • 三、图关系
  • 四、查找和排序
  • 总结


概述

现在是大数据时代,如何高效地处理大量的数据呢?

数据结构的作用:研究数据如何在计算机中进行组织和存储的,使得我们可以高效的获取数据或者修改数据

特点:数学和计算机的结合,代码量大,可以极大地锻炼逻辑思考能力

起源:

        早期计算器: 数学---纯数字之间的关系  +-*/   tan log e, 而今天的数据早已经不再是纯数字的关系

        数据结构:研究数据与数据之间关系的一门学科     数据=数字 + 非数字,操作:增删改查

数据和数据之间的关系: 从两个角度研究数据和数据之间的关系

1.人的角度--理论, 逻辑关系--不依赖于计算机

        线性关系:一个前驱,一个后继             一对一关系  (一个队列或队伍)

        树关系:    一个前驱,多个后记             一对多关系

        网络关系:  N个前驱,N个后继              多对多关系     

2.计算机的角度

        存储关系 : 研究逻辑关系如何存储的

数据与数据之间的关系是静态的。 算法:处理数据和数据关系(的程序)是动态的

//实现任务:1+2+3+....100

//方法一:
        for(int i=1;i<=100;i++)    sum += i;
//方法二:
        (1+最后一个数)*个数/2

算法不是唯一的:解决一个问题有n种算法

如何衡量一个算法执行优劣呢?

从两个方面

1.时间 ---时间复杂度来衡量

                指令的频度:一个算法执行的总次数(输入量的公式)

                时间复杂度: 当数据趋于无穷的时候,频度就是时间复杂度,

                                PD = n^3+ n^2 +n^2 +n + n+1  ,当n->无穷, 时间复杂度 = n^3

                        它是衡量当数据量为无穷的时候,消耗时间的多少        

设计算法考虑:数据的规模, 时间复杂度

有哪些时间复杂度?

        常量复杂度  o(1)    :推荐,输入量增加,算法时间恒定

        线性复杂度o(n)     :数量量增加,运算时间线性增加

        n^2复杂度o(n^2)   :比如两个for

        log复杂度o(log)     :树的操作 

2.空间---空间复杂度

        一般我们很少在意空间问题,一般只从时间复杂度考虑问题

        当输入量/数据量趋于无穷的时候,程序所占用的空间的大小


数据与数据之间的关系

一、线性关系

        特点:一个节点,最多一个前驱,一个后继。头部,无前驱,尾部无后继

        线性关系的存储:

                1.顺序存储:逻辑上相邻,存储上也相邻。(数组)

                优点:可以随机访问

                缺点:删除和插入,需要搬运大量数据,很耗时,不划算。

数组是一次性分配的,可能浪费不够用

                2.链式存储:逻辑上相邻,存储上不相邻 (链表)

                        不能随机访问,只能通过前一个结点,找到下一个节点,

每个节点,除了存放自己的数据之外,还要存放下一个结点的地址

                       优点:按需分配空间,插入删除不需要大量移动

        栈:stack

                栈是一种  先进后出  的线性结构,比如电梯,球桶,死胡同

                只在一端进行插入和删除的线性表,称为栈

                作用:对数组进行逆序

                        1.顺序栈--数组           2.链式栈--链表

        队列:queue               又称FIFO,first input first ouput

                只允许在两端 进行操作,尾部插入,头部删除的一种线性表

                作用: 缓存匹配输入和输出两种不同的速度

               1.顺序存储---使用普通数组实现,发现删除数据的时候,大量的搬移数据

                        变通的方法:环形队列

                2.链式存储---就是使用链表完成FIFO


二、树关系

定义:有且只有一个根,其他分支互不相交。

            每个节点最多只有一个前驱,可以有多个后继

根节点:跟无前驱,叶子节点,无后继

节点的度数:节点的直接子树个数。父节点,子节点:  是相对的

兄弟节点:拥有相同父亲的节点,互为兄弟节点

层次: 根节点层次是1,每经过一个子节点+1. 深度:最大的层次数

用途:        计算机中的目录

二叉树

        每个节点最多有两个两个子节点,称为左和右

        二叉树具有树的一切特性,所以它可以实现树的任何操作

        我们一般使用二叉树代替树结构

满二叉树:        每个节点都有两个子节点,叶子节点除外

完全二叉树:    满二叉树,只有最后一层(叶子节点),不完整

二叉树的遍历:

        遍历:访问只访问一次

        三种遍历方法:

        先序遍历: 跟左右           ,先访问跟,然后左和右 ,跟始终在前面

        中序遍历:左根右        ,先访问左,然后是跟和右, 跟始终在中间

        后序遍历:左右跟        ,跟始终在后面

先序和后序可以知跟,中序分左右

二叉树的存储:

        线性存储,将二叉树布满为满二叉树,然后编号,

根据编号依次放入一个伟大的数组,如果是一个空节点,存放-1

        特点:浪费太大---没有实用价值

        链式存储:画图分析

#include <stdio.h>

struct bnode{
    char ch;  //存放数据
    struct bnode *left,*right; //存放左右子节点的地址
};

struct bnode a,b,c,d,e;

struct btree_front_traval(struct bnode *root)
{
    if(root ==NULL){
        return ;
    }
    
    printf("%c ",root->ch);
    btree_front_traval(root->left);
    btree_front_traval(root->right);  //递归

}


int main()
{
    a.ch='A';  b.ch='B'; c.ch='C';  e.ch='E';

    a.left=&b;    a,right=NULL:
    b.left=&c;    b.right=&d;
    c.left=NULL;  c.right=&NULL;
    d.left=&e;    d.right=NULL;
    e.left=NULL;  e.right=NULL;

struct bnode *root = &a;

printf("front traval:");
btree_front_traval(root);
printf("\n");

    return o;
} 

二叉树的应用:

        哈夫曼树,最优二叉树

        用途:文件的压缩

方法: 定长编码 :每个字符占据的bit数,是固定的

        不定长编码:

                原理:一篇文章,各个字符出现的概率是不一样,如果给概率高的字符一个很短的编码

                        该概率低的字符,一个很长的编码,整片文件所占的空间将被大大压缩。

如何实现对文章的最优编码:

1.扫描整篇,找出文章中所用到的字符

        计算各个字符出现的   概率/频次

2.以这些字符为节点,构建哈夫曼树

3.所有左侧分支 安排0,右侧分支  安排1,则得到编码


特点:节点N个前驱,N个后继

用途:计算机网络     (人际关系网,导航系统.....)

分类:

        有向图:  节点间单向行走        无向图:双向行走

        权:权值--两个节点间的距离/边的长度 

        度:和某个节点直接相连的点,成为该结点的度数         在有向图里,又分为入度和出度

        路径:从一个节点到另一个节点,所经过的所有节点集合成为路径

查找和排序

        1.遍历方法

                领域: 数据量比较小,数据无规律

        2.二分查找

                领域:适合有规律的数据,排序好的数据

#include <stdio.h>

int arr[10] = {2,4,5,7,8,9,11,12,18,22};

int bin_find(int *arr, int cnt, int findval)
{
    int low=0;
    int high =cnt-1;
    int mid;
    
    while(1){
        mid = (low+high)/2;
        if( arr[mid] == findval ){
            return mid;
        }
        if( arr[mid] > findval ){
            high=mid-1;
        }
        if( arr[mid] < findval ){
            low=mid+1;
        }

    }
        
    //如果程序到这里 这个要找的数就不存在 ,low > high
    retuen -1;

}

排序:

        选择排序

for(k=0;k<N-1;k++){
			minpos=k; //遍历之前假设第一个就是最小值
			for(i=k;i<=N-1;i++){
				if( arr[i] < arr[minpos] ){
					minpos=i;
				}
			}
			//congratulation,minpos就是最小值,和k位置交换
			tmp=arr[k];arr[k]=arr[minpos];arr[minpos]=tmp;
		}

        冒泡排序

for(int k=0;k<=N-2;k++){
			for(int i=0;i<=N-k-2;i++){
				if(arr[i] > arr[i+1]){
					int tmp=arr[i];arr[i]=arr[i+1];arr[i+1]=tmp;
				}
			}
		}

        快速排序

        插入排序----链表


总结

数据结构的学习过程中,画图来帮助思考是很有必要的

我这里只是一个大的框架,很多地方还需要去扩展和延申,可能会出现很多不同的情况

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值