数据结构 笔记

一、线性表 (数组,链表,栈,队列)

1.数组 (常见操作:访问、查找、插入、删除)

数组的基本操作有: ① 访问 ② 查找 ③ 插入 ④ 删除

访问

             \;\;\;\;\;\; 数组元素可以直接通过数组下标访问,所以,数组元素的查找是O(1)时间复杂度的。

习题

查找

             \;\;\;\;\;\; 在长度为n的数组里面查找一个数,那么需要通过for循环查找,时间复杂度为 O ( n ) O(n) O(n),如果这个数组是有序的那么,可以通过二分查找将时间复杂度降为:O(logn)

插入

             \;\;\;\;\;\; 数组插入元素:假设需要在数组 a[ ] 下标为k的索引位置插入元素,那么就得将数组长度再开大空间,将 k 到 a.length - 1的数组元素往后挪一位,再将要插入的元素复制给a[k],a[k] = 插入的元素值。

删除

             \;\;\;\;\;\; 删除元素同理,将要删除的元素后面的元素依次往前移一位。

             \;\;\;\;\;\; 插入操作和删除操作都是属于线性复杂度的。所以,正常情况下,如果是在插入和删除操作比较频繁的场合下,数组是不适合的。

2.链表

链表的每个节点值都是由两个域组成,一个是存放元素的数据域(以下称 data域),另一个是指向下一个节点的位置的指针域(以下称next域)

① 头插法
② 尾插法

3.栈

4.队列

二、字符串

三、树与二叉树

哈夫曼树(二叉)与哈夫曼编码

哈夫曼树:是基于贪心算法的思想来设计的树
哈夫曼编码:哈夫曼树的实际应用

概念

(哈夫曼树的概念在后面给出)

权: 树中结点相关的数值

路径长度: 从树中某个结点到另一个结点之间的分支数目(经过的边数)

带权路径长度: 从树的根节点到任意结点的路径长度(经过的边数)与改结点上权值的乘积称为该结点的带权路径长度。

树中所有叶结点的带权路径长度之和称为 该树的带权路径长度
( 树 的 带 权 路 径 长 度 )        W P L = ∑ i = 1 n w i × l i (树的带权路径长度) \;\;\;WPL=\sum_{i=1}^{n}w_i×l_i ()WPL=i=1nwi×li
其中 w i w_i wi 是第 i i i 叶结点所带的权值; l i l_i li 是该叶结点到根结点的路径长度。

例如这颗树:
在这里插入图片描述
( 树 的 带 权 路 径 长 度 )        W P L = 5 × 1 + 15 × 2 + 40 × 3 + 30 × 4 + 10 × 4 = 315 (树的带权路径长度) \;\;\;WPL = 5 × 1 + 15 × 2 + 40 × 3 + 30 × 4 + 10 × 4 = 315 ()WPL=5×1+15×2+40×3+30×4+10×4=315
(叶结点A到根结点的路径长度是1,同理叶结点B、C、D、E到根结点的路径长度分别是:2,3,4,4)

再换一种树:
在这里插入图片描述
( 树 的 带 权 路 径 长 度 )        W P L = 5 × 3 + 15 × 3 + 40 × 2 + 30 × 2 + 10 × 2 = 220 (树的带权路径长度) \;\;\;WPL = 5 × 3 + 15 × 3 + 40 × 2 + 30 × 2 + 10 × 2 = 220 ()WPL=5×3+15×3+40×2+30×2+10×2=220

那么哈夫曼树的概念就是:含有N个带权叶子结点的二叉树中,其中带权路径长度(WPL)最小的二叉树,也称为:最优二叉树

哈夫曼树的建立

  1. 将这N个结点分别作为N棵仅含一个结点的二叉树,构成森林F。(森林:森林是m(m≥0)棵互不相交的树的集合)
  2. 构造一个新结点,并从F中选取 两棵根结点权值最小的树 作为 新结点的左、右子树,并且将新结点的权值置为 左、右子树上根结点的权值之和
  3. 从F中删除刚才选出的两棵树,同时将新得到的树加入F中。
  4. 重复步骤2,3,直至F中只剩下一棵树为止。

题目:设给定权集w={5, 7, 2, 3, 6, 8, 9},试构造关于w的一棵哈夫曼树,并求其加权路径长度WPL。

步骤如下
在这里插入图片描述

在这里插入图片描述
往后的步骤
在这里插入图片描述
在这里插入图片描述
W P L = 6 × 3 + 7 × 3 + 2 × 4 + 3 × 4 + 5 × 3 + 8 × 2 + 9 × 2 = 108 WPL = 6 × 3 + 7 × 3 + 2 × 4 + 3 × 4 + 5 × 3 + 8 × 2 + 9 × 2 = 108 WPL=6×3+7×3+2×4+3×4+5×3+8×2+9×2=108

总结哈夫曼树的重要性质

  1. 每个初始结点最终都成为了叶结点,并且权值越小的结点到根结点的路径长度越大
  2. 构造过程中共新建了N-1个结点(双分支结点),因此哈夫曼树中结点总数为:2N-1
  3. 每次构造都选择2棵树作为新结点的孩子,因此哈夫曼树不存在 度(结点的分支数) 为1的结点。

哈夫曼编码

哈夫曼编码最早用于解决远距离电报通信的数据传输最优化问题。

四、图

图的储存

稠密图 :邻接矩阵
稀疏图:邻接表

五、排序

内排序

外排序

六、查找

七、Java工具

ArrayList

数组的长度不可以发生改变。
但是ArrayList集合的长度是可以随意改变的

对于ArrayList来说,有一个尖括号代表泛型。
泛型:也就是装在集合当中所有元素,全都是统一的什么类型。
注意:泛型也只能是引用类型,不能是基本类型。

注意事项:
对于ArrayList集合来说,直接打印得到的不是地址值,而是内容。
如果内容是空,得到的是空的中括号:[]

ArrayList 简单的创建和使用

package JavaArrayList;

import java.util.ArrayList;

public class Demo01ArrayList {
    public static void main(String[] args) {
        //创建了一个ArrayList集合,集合的名称是List,里面装的全都是String字符串类型的数据。
        //备注:从JDK 1.7+开始,右侧的尖括号内部可以不写内容,但<>本身还是要写的。
        ArrayList<String> list = new ArrayList<>();
        System.out.println(list);

        //向集合当中添加一些数据,需要用到add方法
        list.add("赵丽颖");
        System.out.println(list);
        list.add("迪丽热巴");
        list.add("古力娜扎");
        list.add("马儿扎哈");
        System.out.println(list);

//        list.add(100);//会报错,因为泛型规定了是String的数据类型,100是整形。
    }
}

运行结果:

在这里插入图片描述

ArrayList当中的常用方法

public boolean add(E, e):向集合当中添加元素,参数的类型和泛型一致。
备注:对于ArrayList集合来说:add添加动作一定是成功的,所以返回值可用可不用
但是对于其它的add添加动作不一定是成功的,所以要注意!!!
public E get(int index):从集合当中获取元素,参数是索引编号,返回值就是对应位置的元素
public E remove(int index):从集合当中删除元素,参数是索引编号,返回值就是被删除掉的元素
public int size():获取集合的尺寸长度,返回值是集合中返回的元素个数。

package JavaArrayList;

import java.util.ArrayList;

public class Demo2ArrayListMethod {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        System.out.println(list);//[]

        //像集合中添加元素:add
        boolean success = list.add("柳岩");
        System.out.println(list);//[柳岩]
        System.out.println("添加的动作是否成功:" + success);
        list.add("柳岩");
        list.add("高圆圆");
        list.add("赵又廷");
        list.add("李小璐");
        list.add("贾乃亮");
        System.out.println(list);

        //从集合中获取元素:get,索引值从0开始
        //这个返回类型就是E,至于E是什么取决于尖括号里面是什么<>这里的尖括号里面是String那就是返回String类型。
        String name = list.get(2);
        System.out.println("第2号索引位置是:" + name);

        //从集合中删除元素:remove,索引值从0开始
        String whoRemoved = list.remove(3);
        System.out.println("被删除人是谁:" + whoRemoved);
        System.out.println(list);

        //获取集合的长度,也就是其中元素的个数
        int size = list.size();
        System.out.println(size);
    }
}

运行结果:

在这里插入图片描述
遍历输出集合元素

package JavaArrayList;

import java.lang.reflect.Array;
import java.util.ArrayList;

public class Demo03ArrayListEach {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("迪丽热巴");
        list.add("古力娜扎");
        list.add("伊戈达拉");

        //遍历集合
        for (int i = 0; i < list.size(); ++i) {
            System.out.println(list.get(i));//输出集合里面的第i个元素
        }
    }
}

在这里插入图片描述
小练习:
写一个ArrayListPrint()改变一个输出集合的格式:

题目:
定义以指定格式打印集合的方法(ArrayList类型作为参数),使用{}扩起集合,使用@分隔每个元素
格式参照 {元素@元素@元素}
exp:
System.out.println(list); [10, 20, 30]
printArrayList(list); {10@20@30}

package JavaArrayList;

import java.lang.reflect.Array;
import java.util.ArrayList;

public class Demo03ArrayListPrint {

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        list.add("启裕哥");
        list.add("企郁哥");
        list.add("起钰姐");
        list.add("琦玉姐");
        System.out.println(list);
        System.out.println(" ———————————————————— ");

        printArrayList(list);
    }
        /*
        定义方法的三要素:
        返回值类型:只是进行打印而已,没有运算,没有结果,所以用void
        方法名称:printArrayList
        参数列表:ArrayList
         */

    public static void printArrayList(ArrayList<String> list) {
        //{10@20@30} 格式
        System.out.print("{");
        for (int i = 0; i < list.size(); ++i) {
            String name = list.get(i);
            if (i == list.size() - 1) {
                System.out.println(name + "}");
            } else {
                System.out.print(name + "@");
            }
        }
    }
}
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值