2011-07-20 17:35:49 sun6223508 阅读数 2595
  • 数据迁移:将数据迁移到AWS的6策略

    企业云之旅的第一步通常是将数据迁移到云上。 AWS提供多种数据存储服务,并提供多样的将数据迁移到云端的方法。可能你会想,将数据进行备份还原,收集转移设备数据流,一次性转移大量数据,或者使用专线直连,然后想一个接下来的处理办法。你知道哪种方法适合你的系统结构吗?通过本次在线研讨会,你将对AWS提供的6种数据迁移服务有个大致的了解,主要包括每种迁移方法的优势和不足,以及他们之间的互补策略。

    3539 人正在学习 去看看 CSDN大会

线性表是最基本、最简单、也是最常用的一种数据结构。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。线性表的逻辑结构简单,便于实现和操作。因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。


 线性结构的基本特征为:  1.集合中必存在唯一的一个“第一元素”;  2.集合中必存在唯一的一个 “最后元素” ;  3.除最后一个元素之外,均有 唯一的后继(后件);  4.除第一个元素之外,均有 唯一的前驱(前件)。  由n(n≥0)个数据元素(结点)a1,a2,…,an组成的有限序列。  数据元素的个数n定义为表的长度。  当n=0时称为空表。  常常将非空的线性表(n>0)记作:  (a1,a2,…an)   数据元素ai(1≦i≦n)只是一个抽象的符号,其具体含义在不同的情况下可以不同。  线性表的基本操作  1)MakeEmpty(L) 这是一个将L变为空表的方法  2)Length(L) 返回表L的长度,即表中元素个数  3)Get(L,i) 这是一个函数,函数值为L中位置i处的元素(1≤i≤n)  4)Prev(L,i) 取i的前趋元素  5)Next(L,i) 取i的后继元素  6)Locate(L,x) 这是一个函数,函数值为元素x在L中的位置  7)Insert(L,i,x)在表L的位置i处插入元素x,将原占据位置i的元素及后面的元素都向后推一个位置  8)Delete(L,p) 从表L中删除位置p处的元素  9)IsEmpty(L) 如果表L为空表(长度为0)则返回true,否则返回false  10)Clear(L)清除所有元素  11)Init(L)同第一个,初始化线性表为空  12)Traverse(L)遍历输出所有元素  13)Find(L,x)查找并返回元素  14)Update(L,x)修改元素  15)Sort(L)对所有元素重新按给定的条件排序



2017-12-20 15:54:44 u010173095 阅读数 113
  • 数据迁移:将数据迁移到AWS的6策略

    企业云之旅的第一步通常是将数据迁移到云上。 AWS提供多种数据存储服务,并提供多样的将数据迁移到云端的方法。可能你会想,将数据进行备份还原,收集转移设备数据流,一次性转移大量数据,或者使用专线直连,然后想一个接下来的处理办法。你知道哪种方法适合你的系统结构吗?通过本次在线研讨会,你将对AWS提供的6种数据迁移服务有个大致的了解,主要包括每种迁移方法的优势和不足,以及他们之间的互补策略。

    3539 人正在学习 去看看 CSDN大会

前面学习一种数据结构-队列,在队列的实现中有一种实现叫链表实现,今天就学习一下链表这种数据结构。

链表

百度百科权威描述:

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。

使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。链表可以在多种编程语言中实现。像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C++和Java依靠易变工具(这个不知道是什么意思)来生成链表。

根据上面关于链表的描述,链表有一下特点:

  1. 存储结构是非连续的、非顺序的;
  2. 链表相邻的节点有关系;
  3. 链表的插入节点和删除节点很方便,只要修改节点关系即可;
  4. 链表遍历取值较为复杂,需要从头取值,知道找到节点为止;

单向链表

单向链表,每个节点都包含下个节点的信息,最后一个节点除外(最后一个节点的后一个节点为null)。

ps:前面用链表实现队列的时候,就可以认为是一个单向链表

首先先定义一个接口,让所有的实现都实现这个接口:

public interface Linked<E> {

    /**
     * 返回当前链表的数量
     * @return size
     */
    public int size();

    /**
     * 在尾部增加一个节点, 并返回该节点
     * @param e
     * @return E
     */
    public E add(E e);

    /**
     * 删除一个怨怒射
     * @param i 元素位置
     * @return E
     */
    public E remove(int i);

    /**
     * 在指定位置插入一条元素
     * @param e 被插入的元素
     * @param index 被插入的位置的元素
     * @return E
     */
    public E insert(E e, int index);

    /**
     * 取出某个位置的元素
     * @param i 要取出的位置
     * @return E
     */
    public E get(int i);
}

下面用java实现一个单向链表:

public class SingleLinked<E> implements Linked<E> {


    // 头部节点
    private Node head;
    //尾部节点
    private Node tail;
    //链表元素的个数
    private int size;




    @Override
    public int size () {
        return this.size;
    }

    /**
     * 如果head为空,则说明当前尚无节点,就把添加的值赋给头节点,
     * 把头结点的值赋给tail节点
     * 如果head节点不为空,则把新增的节点赋值给tail节点的下一个节点
     * 并把新节点赋值给tail
     * @param e
     * @return
     */
    @Override
    public E add (E e) {
        if (null == head) {
            head = new Node(e, null);
            tail = head;
        } else {
            Node temp = new Node(e, null);
            tail.next = temp;
            tail = temp;
        }
        size++;
        return e;
    }

    /**
     * 删除指定位置的节点
     * 删除逻辑:
     * 如果删除的是head,判断tail是否和head相等,如果相等,就把head和tail设成null
     * 如果不相等,就把head的next设成head
     * 如果删除的不是head,就把pre的next设成删除节点的next
     * @param index
     * @return
     */
    @Override
    public E remove (int index) {

        if (index > size) {
            return null;
        }

        Node pre = null;
        Node next = head;
        Node temp = null;
        int sum = 0;
        while (sum <= index) {

            if (sum == index) {
                if (null == pre)  {
                    temp = head;
                    if (tail == head) {
                        head = null;
                        tail = null;
                    } else {
                        head = head.next;
                    }
                } else {
                    temp = next;
                    pre.next = next.next;
                }
                break;
            } else {
                pre = next;
                next = pre.next;
            }
            sum++;
        }

        size--;
        return temp.e;
    }

    /**
     * 在指定位置插入节点
     * 操作逻辑:
     * 找到指定位置的节点,把上一个节点的下一个节点属性设为要插入的节点,插入的节点的下一个节点设为原来位置的节点;
     * 如果插入的位置为head节点的位置,则把插入的节点设为head
     *
     * @param e 被插入的元素
     * @param index 被插入的位置的元素
     * @return
     */
    @Override
    public E insert (E e, int index) {

        if (index > size) {
            return null;
        }

        Node pre = null;
        Node next = head;
        Node eNode = new Node(e, null);

        int sum = 0;
        while (sum <= index) {

            if (sum == index) {
                eNode.next = next;
                if (null == pre)  {
                    eNode.next = head;
                    head = eNode;
                } else {
                    pre.next = eNode;
                }

                break;
            } else {
                pre = next;
                next = pre.next;
            }
            sum++;
        }

        size++;
        return e;
    }

    /**
     * 默认取出第一个元素
     * @return
     */
    @Override
    public E get() {
        return this.get(0);
    }

    /**
     * 取出指定位置的节点
     * 取值逻辑:
     * 如果取第一个节点,判断头head和tail是否相等,如果相等,就把head和tail都赋值为null,
     * 如果不相等,就把取值节点的上一个节点(pre)的下一个节点设为取值节点的下一个节点;
     * 如果取的不是第一个节点,判断是否是tail节点,如果是就把上一个节点设为tail
     * 如果不是,就把取值节点的上一个节点(pre)的下一个节点设为取值节点的下一个节点;
     * @param i 要取出的位置
     * @return
     */
    @Override
    public E get (int i) {

        Node next = head;
        Node pre = head;
        Node temp ;
        int sum = 0;
        if (i >= size) { // 查找的位置大于总数量时
            return null;
        }
        for (;;) {
            if (sum == i) {
                temp = next;
                if (i == 0) {// 如果取第一个就把下一个节点设为head
                    if (head.equals(tail)) {
                        head = null;
                        tail = null;
                    } else {
                        head = pre.next;
                    }
                } else {
                    if (null == next.next) {
                        pre.next = next.next;
                        tail = pre;
                    } else {
                        pre.next = next.next;
                    }
                }
                break;
            } else {
                pre = next;
                next = next.next;
            }
            sum++;
        }

        E e = null;
        if (null != temp) {
            e = temp.getE();
            size--;
        }
        return e;
    }

    /**
     * 用于存储链表的结构
     */
    private class Node {

        private E e;
        private Node next;

        public Node () {
        }

        public Node (E e) {
            this.e = e;
        }

        public Node (E e, Node next) {
            this.e = e;
            this.next = next;
        }

        public E getE () {
            return e;
        }

        public void setE (E e) {
            this.e = e;
        }

        public Node getNext () {
            return next;
        }

        public void setNext (Node next) {
            this.next = next;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof SingleLinked.Node)) {
                return false;
            } else {
                Node node = (Node) o;

                if (!e.equals(node.e)) return false;
                return next != null ? next.equals(node.next) : node.next == null;
            }
        }

        @Override
        public int hashCode() {
            int result = e.hashCode();
            result = 31 * result + (next != null ? next.hashCode() : 0);
            return result;
        }
    }

}

测试代码:

public class LinkedTest {


    public static void main(String[] args) {

        SingleLinked<String> singleLinked = new SingleLinked<>();
        singleLinked.add("123");
        singleLinked.add("456");
        singleLinked.add("789");
        singleLinked.add("147");
        singleLinked.add("258");

        System.out.println("链表的大小===" + singleLinked.size());

        System.out.println("第一个节点==" + singleLinked.get(0));

        System.out.println("链表的大小===" + singleLinked.size());

        //singleLinked.insert(""369", 0);
        System.out.println("删除的节点===" + singleLinked.remove(2));
        System.out.println("链表的大小===" + singleLinked.size());


        //System.out.println("第二个节点==" + singleLinked.get());
        //System.out.println("第三个节点==" + singleLinked.get());
        //System.out.println("第四个节点==" + singleLinked.get());
        //System.out.println("第五个节点==" + singleLinked.get());
        //System.out.println("第六个节点==" + singleLinked.get());
        //System.out.println("第七个节点==" + singleLinked.get());

    }
}

测试结果:

链表的大小===5
第一个节点==123
链表的大小===4
删除的节点===147
链表的大小===3

上面的一个简单实现是我用业余时间修修改改几天才写出来的,深刻体会到做比说难。在写的过程中发现,虽然百科里面解释说链表插入删除比较简单,但是实现过程中发现并不简单。
经常听说的一个冷笑话,如何把大象装进冰箱里?
第一步,打开冰箱们;第二部把大象塞进去;第三部,关上冰箱们;

如何插入一个节点:
第一步,找到上一个节点;第二部,把节点的下一个位置设为插入的节点;第三部把插入节点的下一个节点设为原来节点的下一个节点;

解释起来非常的简单,实际实现起来并不简单,查找节点要从头开始遍历,还要考虑其它问题;同理删除节点也存在同样的问题;

***ps:
代码中的实现都是以位置来决定插入位置,而不是以已有节点来决定插入位置,如果由节点决定,后插操作相对容易一点,前插操作依然需要遍历*

以节点决定插入位置后插实现:

 /**
     * 后插实现
     * @param e 
     * @param node 
     * @return
     */
    public E insert (E e, Node node) {

        if (null != node ) {
            Node temp = new Node(e);
            node.next = temp;
            tail = temp;
            size++;
        }

        return e;
    }

前插实现和SingleLinked中的插入实现类似就不再写了。

因此,单向链表优化方向是减少删除和插入时查找节点的时间复杂度。目前的实现是通过从头开始遍历直到找到节点为止,时间复杂读为O(n),如果能根据节点或者位置直接找到要操作的节点,就能减少时间复杂度到O(1);

基于以上分析,要建立位置或者节点与节点的对应关系。
我目前的想法是用节点的hashcode与节点的上一个节点简历对应关系,至于index位置因为随着插入和删除会随时变化不具备唯一型暂不考虑;

修改后的插入和删除:

private Map<String, Node> map = new HashMap<>();

public E add (E e) {
        String hashcode;
        if (null == head) {
            head = new SingleLinkedTwo.Node(e, null);
            hashcode = String.valueOf(head.hashCode());
            tail = head;
            map.put(hashcode, null);
        } else {
            SingleLinkedTwo.Node temp = new SingleLinkedTwo.Node(e, null);
            hashcode = String.valueOf(temp.hashCode());
            tail.next = temp;
            map.put(hashcode, tail);
            tail = temp;
        }
        size++;
        return e;
    }

public E remove (Node node) {

        String hashcoed = String.valueOf(node.hashCode());
        Node temp = map.get(hashcoed);
        E e = node.e;
       if (null == temp) {
           head = null;
           head = head.next;
           if (null == head) {
               tail = null;
           }
       } else {
           temp.next = node.next;
           if (null == node.next) {
                tail = temp;
           }
       }

        size--;
        return e;
    }

上面实现了两个方法,只是为了表达自己的想法,没有测试是否正确。

总结

这次学习了解了链表的特征,目前先实现一个单向链表,后面继续实现双向链表和循环链表。

2019-01-16 14:52:36 o279642707 阅读数 261
  • 数据迁移:将数据迁移到AWS的6策略

    企业云之旅的第一步通常是将数据迁移到云上。 AWS提供多种数据存储服务,并提供多样的将数据迁移到云端的方法。可能你会想,将数据进行备份还原,收集转移设备数据流,一次性转移大量数据,或者使用专线直连,然后想一个接下来的处理办法。你知道哪种方法适合你的系统结构吗?通过本次在线研讨会,你将对AWS提供的6种数据迁移服务有个大致的了解,主要包括每种迁移方法的优势和不足,以及他们之间的互补策略。

    3539 人正在学习 去看看 CSDN大会

数据结构分类

数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成 。
常用的数据结构有:数组,栈,队列,链表,树,散列表,堆,图等,如图所示

在这里插入图片描述

每一种数据结构都有着独特的数据存储方式,下面为大家介绍它们的结构和优缺点

1、数组

数组是可以再内存中连续存储多个元素的结构,在内存中的分配也是连续的,数组中的元素通过数组下标进行访问,数组下标从0开始。例如下面这段代码就是将数组的第一个元素赋值为 1。

int[] data = new int[100];
data[0]  = 1;

优点:
1、按照索引查询元素速度快
2、按照索引遍历数组方便

缺点:
1、数组的大小固定后就无法扩容了
2、数组只能存储一种类型的数据
3、添加,删除的操作慢,因为要移动其他的元素。

适用场景:
频繁查询,对存储空间要求不大,很少增加和删除的情况。

2、栈

栈是一种特殊的线性表,仅能在线性表的一端操作,栈顶允许操作,栈底不允许操作。 栈的特点是:先进后出,或者说是后进先出,从栈顶放入元素的操作叫入栈,取出元素叫出栈。

在这里插入图片描述
在这里插入图片描述

栈的结构就像一个集装箱,越先放进去的东西越晚才能拿出来,所以,栈常应用于实现递归功能方面的场景,例如斐波那契数列

3、队列

队列与栈一样,也是一种线性表,不同的是,队列可以在两端进行操作,一端添加元素,在另一端取出元素,也就是:先进先出。从一端放入元素的操作称为入队,取出元素为出队,示例图如下

在这里插入图片描述
适用场景:因为队列先进先出的特点,在多线程阻塞队列管理中非常适用

4、链表

链表是物理存储单元上非连续的、随机的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,每个元素包含两个域,它包括两个域;存储数据元素信息的域称为数据域;存储直接后继存储位置的域称为指针域。指针域中存储的信息称为指针或链,

例如单链表,双向链表,循环链表等。

在这里插入图片描述

链表的优点:
链表是很常用的一种数据结构,不需要初始化容量,可以任意加减元素;
添加或者删除元素时只需要改变前后两个元素结点的指针域指向地址即可,所以添加,删除很快;

缺点:
因为含有大量的指针域,占用空间较大;
查找元素需要遍历链表来查找,非常耗时。

适用场景:
数据量较小,需要频繁增加,删除操作的场景

5、树

树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做 “树” 是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:

每个节点有零个或多个子节点;
没有父节点的节点称为根节点;
每一个非根节点有且只有一个父节点;
除了根节点外,每个子节点可以分为多个不相交的子树;
在日常的应用中,我们讨论和用的更多的是树的其中一种结构,就是二叉树。

在这里插入图片描述

二叉树是树的特殊一种,具有如下特点:

1、每个结点最多有两颗子树,结点的度最大为2。
2、左子树和右子树是有顺序的,次序不能颠倒。
3、即使某结点只有一个子树,也要区分左右子树。

二叉树是一种比较有用的折中方案,它添加,删除元素都很快,并且在查找方面也有很多的算法优化,所以,二叉树既有链表的好处,也有数组的好处,是两者的优化方案,在处理大批量的动态数据方面非常有用。

扩展:
二叉树有很多扩展的数据结构,包括平衡二叉树、红黑树、B+树等,这些数据结构二叉树的基础上衍生了很多的功能,在实际应用中广泛用到,例如mysql的数据库索引结构用的就是B+树,还有HashMap的底层源码中用到了红黑树。这些二叉树的功能强大,但算法上比较复杂,想学习的话还是需要花时间去深入的。

6、散列表
散列表,也叫哈希表,是根据关键码和值 (key和value) 直接进行访问的数据结构,通过key和value来映射到集合中的一个位置,这样就可以很快找到集合中的对应元素。

记录的存储位置=f(key)

这里的对应关系 f 成为散列函数,又称为哈希 (hash函数),而散列表就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里,这种存储空间可以充分利用数组的查找优势来查找元素,所以查找的速度很快。

哈希表在应用中也是比较常见的,就如Java中有些集合类就是借鉴了哈希原理构造的,例如HashMap,HashTable等,利用hash表的优势,对于集合的查找元素时非常方便的,然而,因为哈希表是基于数组衍生的数据结构,在添加删除元素方面是比较慢的,所以很多时候需要用到一种数组链表来做,也就是拉链法。拉链法是数组结合链表的一种结构,较早前的hashMap底层的存储就是采用这种结构,直到jdk1.8之后才换成了数组加红黑树的结构,其示例图如下:

在这里插入图片描述
从图中可以看出,左边很明显是个数组,数组的每个成员包括一个指针,指向一个链表的头,当然这个链表可能为空,也可能元素很多。我们根据元素的一些特征把元素分配到不同的链表中去,也是根据这些特征,找到正确的链表,再从链表中找出这个元素。

哈希表的应用场景很多,当然也有很多问题要考虑,比如哈希冲突的问题,如果处理的不好会浪费大量的时间,导致应用崩溃。

7、堆

堆是一种比较特殊的数据结构,可以被看做一棵树的数组对象,具有以下的性质:

堆中某个节点的值总是不大于或不小于其父节点的值;

堆总是一棵完全二叉树。

将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

堆的定义如下:n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。
(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4…n/2),满足前者的表达式的成为小顶堆,满足后者表达式的为大顶堆,这两者的结构图可以用完全二叉树排列出来,示例图如下:

在这里插入图片描述

因为堆有序的特点,一般用来做数组中的排序,称为堆排序。

8、图

图是由结点的有穷集合V和边的集合E组成。其中,为了与树形结构加以区别,在图结构中常常将结点称为顶点,边是顶点的有序偶对,若两个顶点之间存在一条边,就表示这两个顶点具有相邻关系。

按照顶点指向的方向可分为无向图和有向图:

有向图

在这里插入图片描述

图是一种比较复杂的数据结构,在存储数据上有着比较复杂和高效的算法,分别有邻接矩阵 、邻接表、十字链表、邻接多重表、边集数组等存储结构,这里不做展开,读者有兴趣可以自己学习深入。

引用
https://blog.csdn.net/yeyazhishang/article/details/82353846
数据结构与算法分析

2018-02-28 10:23:23 qq_33733970 阅读数 2770
  • 数据迁移:将数据迁移到AWS的6策略

    企业云之旅的第一步通常是将数据迁移到云上。 AWS提供多种数据存储服务,并提供多样的将数据迁移到云端的方法。可能你会想,将数据进行备份还原,收集转移设备数据流,一次性转移大量数据,或者使用专线直连,然后想一个接下来的处理办法。你知道哪种方法适合你的系统结构吗?通过本次在线研讨会,你将对AWS提供的6种数据迁移服务有个大致的了解,主要包括每种迁移方法的优势和不足,以及他们之间的互补策略。

    3539 人正在学习 去看看 CSDN大会
什么是数据结构?

数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。简单来说,数据结构就是设计数据以何种方式组织并存储在计算机中。

数据结构的分类

数据结构按照其逻辑结构可分为线性结构、树结构、图结构

线性结构:数据结构中的元素存在一对一的相互关系
树结构:数据结构中的元素存在一对多的相互关系
图结构:数据结构中的元素存在多对多的相互关系

栈(Stack)是一个数据集合,可以理解为只能在一端进行插入或删除操作的列表。
栈的特点:后进先出(last-in, first-out)
栈的基本操作:

进栈(压栈):push
出栈:pop
取栈顶:gettop

栈的Python实现:

不需要自己定义,使用列表结构即可。
1.进栈函数:append
2.出栈函数:pop
3.查看栈顶函数:li[-1]

链表

链表中每一个元素都是一个对象,每个对象称为一个节点,包含有数据域key和指向下一个节点的指针next。通过各个节点之间的相互连接,最终串联成一个链表。
节点定义:

class Node(object):    
    def __init__(self, item):        
        self.item = item        
        self.next = None

建立链表

头插法:
尾插法:

双链表

双链表中每个节点有两个指针:一个指向后面节点、一个指向前面节点。

哈希表(Hash Table,又称为散列表),是一种线性表的存储结构。哈希表由一个顺序表(数组)和一个哈希函数组成。哈希函数h(k)将元素k作为自变量,返回元素的存储下标。

解决哈希冲突——拉链法

拉链法:哈希表每个位置都连接一个链表,当冲突发生时,冲突的元素将被加到该位置链表的最后。

哈希表在Python中的应用:

字典与集合都是通过哈希表来实现的;

二叉树:

二叉树的链式存储:将二叉树的节点定义为一个对象,节点之间通过类似链表的链接方式来连接。
节点定义:

class BiTreeNode:    
    def __init__(self, data): 
        self.data = data
        self.lchild = None
        self.rchild = None

待补充~

2019-11-26 23:01:07 weixin_45380951 阅读数 8
  • 数据迁移:将数据迁移到AWS的6策略

    企业云之旅的第一步通常是将数据迁移到云上。 AWS提供多种数据存储服务,并提供多样的将数据迁移到云端的方法。可能你会想,将数据进行备份还原,收集转移设备数据流,一次性转移大量数据,或者使用专线直连,然后想一个接下来的处理办法。你知道哪种方法适合你的系统结构吗?通过本次在线研讨会,你将对AWS提供的6种数据迁移服务有个大致的了解,主要包括每种迁移方法的优势和不足,以及他们之间的互补策略。

    3539 人正在学习 去看看 CSDN大会

啥是数据结构

数据结构是计算机存储组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。

数据结构的分类

数据结构分为8类有:数组、栈、队列、链表、树、散列表、堆、图。数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成 。

1、数组

数组是可以在内存中连续存储多个元素的结构,在内存中的分配也是连续的,数组中的元素通过数组下标进行访问,数组下标从0开始。

2、栈

栈是一种特殊的线性表,仅能在线性表的一端操作,栈顶允许操作栈底不允许操作。 栈的特点是:先进后出,或者说是后进先出,从栈顶放入元素的操作叫入栈,取出元素叫出栈。

3、队列

队列与栈一样,也是一种线性表,不同的是,队列可以在一端添加元素,在另一端取出元素,即:先进先出。从一端放入元素的操作称为入队,取出元素为出队。

4、链表

链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,每个元素包含两个结点,一个是存储元素的数据域 (内存空间),另一个是指向下一个结点地址的指针域。根据指针的指向,链表能形成不同的结构,例如单链表,双向链表,循环链表等。
+`

5、树

树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做 “树” 是因为它看起来像一棵倒挂的树,换言之,它是根朝上,而叶朝下的。

6、散列表

散列表,也叫哈希表,是根据关键码 (key和value) 直接进行访问的数据结构,通过key和value来映射到集合中的一个位置,这样就可以很快找到集合中的对应元素。

7、堆

堆是一种比较特殊的数据结构,可以被看做一棵树的数组对象,具有以下的性质:堆中某个节点的值总是不大于或不小于其父节点的值堆总是一棵完全二叉树。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

8、图

图是由结点的有穷集合V边的集合E组成。其中,为了与树形结构加以区别,在图结构中常常将结点称为顶点,边是顶点的有序偶对,若两个顶点之间存在一条边,就表示这两个顶点具有相邻关系。

数据结构基础

阅读数 26

数据结构之队列

阅读数 297

没有更多推荐了,返回首页