一、什么叫数据结构?

数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合。“结构”就是指数据元素之间存在的关系,分为逻辑结构和存储结构。

程序 = 数据结构 + 算法 

1、数据的逻辑结构

指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后间关系,而与他们在计算机中的存储位置无关。逻辑结构包括:

1.集合:数据结构中的元素之间除了“同属一个集合” 的相互关系外,别无其他关系;

2.线性结构:数据结构中的元素存在一对一的相互关系;(表)

3.树形结构:数据结构中的元素存在一对多的相互关系;(倒悬树)

4.图形结构:数据结构中的元素存在多对多的相互关系。(地图)

2、数据的物理(内存)结构

指数据的逻辑在计算机存储空间的存放形式。

1.顺序结构(数组)

数组存储在连续的内存空间中,用数据元素的相对位置来表示关系。

2.链式结构(链表)

数据元素存储在彼此独立的内存空间中,每个独立的元素也叫做节点,每个数据元素中增加一个数据项用来存储其他元素的地址,用来表示元素之间的关系。

逻辑结构与物理结构的关系

表   -->   顺序 、链式
         树   -->   顺序 、链式
         图   -->   顺序 + 链式

A.顺序结构实现

  • 底层实现:

    数组:Array,是有序的元素序列,数组是在内存中开辟⼀段连续的空间,并在此空间存放元素。
  • 特点:1.按照顺序排列,每个元素都带有标号;2.除了有标号是连续的,内存中的物理空间也是连续的。
  • 优缺点:查询快,增删慢。
package day16_17data.Arr;import java.util.Arrays;/*
数据结构分为逻辑结构 和 存储(物理)结构
逻辑结构:集合: 数据元素同属于一个集体,但是元素之间没有任何关系线性结构: 数据元素之间存在一对一的关系(表)树型结构: 数据元素之间存在一对多的关系(倒悬树)图型结构: 数据元素之间存在多对多的关系(地图)物理(内存)结构:顺序结构(数组)数组存储在连续的内存空间中,用数据元素的相对位置来表示关系.链式结构(链表)数据元素存储在彼此独立的内存空间中,每个独立的元素也叫做节点,每个数据元素中增加一个数据项用来存储其他元素的地址,用来表示元素之间的关系.逻辑结构和物理结构之间的关系:表   ->   顺序  链式树   ->   顺序  链式图   ->   顺序 + 链式
------------------------------------------------------------------------------
顺序结构:底层实现:数组目的: 为了让外部类看起来是一个可变长的数组1.向集合(this)中末尾添加元素2.向集合index的位置中插入obj元素3.删除指定位置(index)上的元素,并且返回删除的元素4.删除第一个指定元素(obj)5.替换指定位置上的元素,替换成obj,并且返回被替换的元素6.从集合中获得指定位置(index)的元素7.获得集合中的元素个数8.判断集合中是否存在指定元素obj9.判断集合是否为空:没有有效元素是空10.打印出在集合中的有效元素*/
public class ArraysDemo01 {//成员变量Object[] arr = new Object[5];int size = 0;//表示有效元素个数//1.向集合(this)中末尾添加元素public void add(Object obj){//判断有效个数是否超过数组的长度if(size == arr.length){//数组扩容arr = Arrays.copyOf(arr,arr.length + 5);}//arr[arr.length-1] = obj;//添加到末尾//将元素添加到数组中arr[size] = obj;//数组个数+1size++;}//2.向集合index的位置中插入obj元素public void add(int index,Object obj){//解决越界问题if(index < 0 || index > size - 1){return;}//数组扩容if(size == arr.length){arr = Arrays.copyOf(arr,arr.length + 5);}for (int i = size - 1 ; i >= index ; i--) {arr[i] = arr[i-1];}arr[index] = obj;size++;}//3.删除指定位置(index)上的元素,并且返回删除的元素public Object remove(int index){//解决越界问题if(index > size - 1 || index < 0){return null;}//将被删除的元素保存下来Object o = arr[index];for (int i = index + 1; i < size; i++) {arr[i - 1] = arr[i];}size--;return o;}//4.删除第一个指定元素(obj)public void remove(Object obj){for (int i = 0; i < size; i++) {if (obj.equals(arr[i])){//如果相同remove(i);break;}}}//5.替换指定位置上的元素,替换成obj,并且返回被替换的元素public Object set(int index,Object obj){//解决越界问题if(index > size - 1 || index < 0){return null;}//保存index位置上的元素Object o = arr[index];//替换元素arr[index] = obj;return o;}//6.从集合中获得指定位置(index)的元素public Object get(int index){return arr[index];}// 7.获得集合中的元素个数 -> sizepublic int size(){return size;}// 8.判断集合中是否存在指定元素objpublic boolean contains(Object obj){for (int i = 0; i < size; i++) {if(obj.equals(arr[i])){return true;}}return false;}//9.判断集合是否为空:没有有效元素是空public boolean isEmpty(){return size == 0;}//10.打印出在集合中的有效元素public String toString(){StringBuilder sb = new StringBuilder("[");for (int i = 0; i < size; i++) {sb.append(arr[i] + ",");}//去除最后一位//sb.deleteCharAt(sb.length()-1);//sb.append("]");sb.replace(sb.length()-1,sb.length(),"]");//字符串的拼接return sb.toString();}
}public class MainArr01 {public static void main(String[] args) {ArraysDemo01 list = new ArraysDemo01();list.add(25);list.add(8);System.out.println(list);list.add(1,"hi");//指定位置+System.out.println(list);list.remove(0);list.contains("hi");System.out.println(list.toString());//[hi,null]}
}

B.链式结构实现

  • 底层实现:节点(data数据 + next下一个节点的引用)

    linked list,由⼀系列结点node(链表中每⼀个元素称为结点)组成,结点可以在运⾏时i动态⽣成。每个结点包括两个部分:⼀个是存储数据元素的数据域,另⼀个是存储下⼀个结点地址的指针域。
  • 特点:1.链表是内存中固定顺序,但是他的物理空间不连续
               2.没有下标,并且从头节点开始
               3.所有节点的访问,都必须通过头节点
               4.head(头节点): 只存next,不存data
               5.head.next = null -> 空链表
  • 三种类型的链表:1.单向链表:只有头节点,只能从头节点出发;2.双向链表:有头节点和尾结点,可以从头或者尾出发;3.循环链表:尾节点指向头节点,可以从任意位置开始。
  • 优缺点:查询慢,插入、删除效率高;

public class SingleLinkDemo {//链表中只存在节点private Node head = new Node();//初始化Nodepublic int size = 0;//表示有效元素个数//成员内部类public class Node{public Object data;//存储数据public Node next;//下一个节点的引用}//获取index之前的一个节点public Node prevNode(int index){/*if (index > size - 1 || index < 0){return null;}*///获取头节点Node node = head;//找到index下标前的一个节点位置for (int i = 0; i < index; i++) {node = node.next;}return node;}//1.向集合(this)中末尾添加元素public void add(Object obj){//获取头节点Node node = head;//判断下一个节点是否为空while(node.next != null){//将节点往下移动一位node = node.next;}//新建节点Node newNode = new Node();//存储新节点的数据newNode.data = obj;//上一个节点指向新的节点node.next = newNode;//节点个数+1size++;}//2.向集合index的位置中插入obj元素public void add(int index,Object obj){//获取头节点Node node = head;//找到index下标前的一个节点位置for (int i = 0; i < index; i++) {node = node.next;}//Node node = prevNode(index);//插入新的节点Node newNode = new Node();newNode.data = obj;//插入新节点://a.新节点的下一个节点是原来的节点newNode.next = node.next;//b.node的下一个节点等于新的节点node.next = newNode;//元素个数+1size++;}//3.删除指定位置(index)上的元素,并且返回删除的元素public Object remove(int index){//找到index之前的一个节点Node node = prevNode(index);//保存index位置上的数据Object o = node.next.data;node.next = node.next.next;size--;return o;}// 4.删除第一个指定元素(obj)public void remove(Object obj){Node node = head;//假设下标int index = -1;//方式一:while(node.next != null){index++;node = node.next;//判断node节点上的数据和 obj是否相同if(node.data.equals(obj)){remove(index);break;}}//方式二:/*while(node.next.data != obj){node = node.next;}node.next = node.next.next;*///方式三:/*for (;node.next.data != obj; index++) {node = node.next;}remove(index);*///方式四:/*for (int i = 0; i < size; i++) {if(node.next.data != obj){node = node.next;}}size--;*/}//5.替换指定位置上的元素,替换成obj,并且返回被替换的元素public Object set(int index,Object obj){Node node = prevNode(index + 1);Object o = node.data;node.data = obj;return o;}// 6.从集合中获得指定位置(index)的元素public Object get(int index){//获取index当前节点位置Node node = prevNode(index + 1);return node.data;}//  7.获得集合中的元素个数public int size(){//会产生栈溢出//return size();return size;}//  8.判断集合中是否存在指定元素objpublic boolean contains(Object obj){Node node = head;while (node.next != null){node = node.next;if(node.data.equals(obj)){return true;}}return false;}//  9.判断集合是否为空:没有有效元素是空public boolean isEmpty(){return size == 0;}public String toString(){StringBuilder sb = new StringBuilder("[");//获取链表中的元素Node node = head;while (node.next != null){node = node.next;sb.append(node.data + ",");}return sb.toString();}}public class MainLink {public static void main(String[] args) {SingleLinkDemo slink = new SingleLinkDemo();slink.add(1);slink.add(2);slink.add(3);slink.add(4);slink.add(2,10);System.out.println(slink);slink.isEmpty();slink.get(1);slink.contains(2);slink.remove(0);}
}

二、常见的数据结构

数据存储的常⽤结构有:栈、队列、数组、链表和红⿊树。

1、栈(Stack)

栈:stack,⼜称堆栈,它是运算受限的线性表,其限制是仅允许在标的⼀端进⾏插⼊和删除操作,不允许在其他任何位置进⾏添加、查找、删除等操作。

特点:

  • 先进后出(即,存进去的元素,要在后它后⾯的元素依次取出后,才能取出该元素)。
  • 栈的⼊口、出⼝的都是栈的顶端位置。
压栈:

就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底⽅向移动⼀ 个位置。
弹栈:
就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶⽅向移动⼀个位置。

自定义代码实现栈 (数组)

/*
栈
用数组实现
*/
public class ArraysDemo01 <T>{private Object[] data;//存储数据的数组private int size = 0;//表示元素有效个数ArraysDemo01(){data = new Object[10];//初始化数组长度}ArraysDemo01(int cap){data = new Object[cap];//初始化数组长度}//压栈public void push(T t){//数组扩容if(size == data.length){data = Arrays.copyOf(data,data.length + 5);}/* 将obj元素添加到数组中data[size] = obj;//有效个数+1size++;*///等同于以上的写法data[size++] = t;}//弹栈public T pop(){//有效个数的下标 size-1/*T t = (T)data[size - 1];size--;*/return (T)data[--size];//弹出去一个 -1}//打印出在集合中的有效元素public String toString(){StringBuilder sb = new StringBuilder("[");for (int i = 0; i < size; i++) {sb.append(data[i] + ",");}//去除最后一位//sb.deleteCharAt(sb.length()-1);//sb.append("]");sb.replace(sb.length()-1,sb.length(),"]");//字符串的拼接return sb.toString();}}
//数组实现栈测试
public class Main01 {public static void main(String[] args) {ArraysDemo01 arrStack = new ArraysDemo01();arrStack.push(22);arrStack.push("xixi");System.out.println(arrStack);//[22,xixi]arrStack.pop();System.out.println(arrStack);//[22]}
}

自定义代码实现栈 (链表)

/*链表方式实现栈*/
public class LinkDemo02 {//头节点private Node head = new Node();//节点类public class Node{public Object data;public Node next;}//压栈public void push(Object obj){//创建新的节点Node newNode = new Node();newNode.data = obj;while (head.next != null){newNode.next = head.next;}//让头节点的next指向新加入的节点head.next = newNode;}//弹栈public Object pop(){//保存被弹出的数据Node node = head.next;//让头节点指向下下节点head.next = head.next.next;//获取被弹出的节点的数据return node.data;}}
//链表实现栈测试
public class Main02 {public static void main(String[] args) {LinkDemo02 linkStack = new LinkDemo02();linkStack.push("xii");linkStack.push(5555);System.out.println(linkStack);linkStack.pop();System.out.println(linkStack);}
}

2.队列(Queue)

队列:queue,简称队,它同堆栈⼀样,也是⼀种运算受限的线性表,其限制是仅允许在表
的⼀端进⾏插⼊,⽽在表的另⼀端进⾏删除。
特点:
  • 先进先出(即,存进去的元素,要在后它前⾯的元素依次取出后,才能取出该元素)。
  • 队列的⼊⼝、出⼝各占⼀侧。 

自定义代码实现队列(链表)也可以通过数组实现

  /*链表实现队列*/public class LinkQueueDemo {//单链表作为成员变量使用private SingleLinkDemo link = new SingleLinkDemo();//入队:public void push(Object obj){link.add(0,obj);}//出列:public Object pop(){//获取元素Object o = link.get(link.size() - 1);//删除元素link.remove(link.size() - 1);return o;}@Overridepublic String toString() {return link.toString();}}
public class MainQueue {public static void main(String[] args) {LinkQueueDemo q = new LinkQueueDemo();q.push(55);q.push("55555");;System.out.println(q);q.pop();System.out.println(q);}
}

数组跟链表看上面顺序结构跟链式结构的解释。

3.二叉树:红黑树

⼆叉树:binary tree ,是每个结点不超过2的有序树(tree) 。
⼆叉树是每个节点最多有两个⼦树的树结构。顶上的叫根结点,两边被称作“左⼦树”和“右⼦树”。
红黑数的本身就是一颗二叉查找树。
红⿊树的约束:
1. 节点可以是红⾊的或者⿊⾊的
2. 根节点是⿊⾊的3. 叶⼦节点(特指空节点)是⿊⾊的
4. 每个红⾊节点的⼦节点都是⿊⾊的
5. 任何⼀个节点到其每⼀个叶⼦节点的所有路径上⿊⾊节点数相同
红⿊树的特点:
速度特别快,趋近平衡树,查找叶⼦元素最少和最多次数不多于⼆倍
关于树的详细了解 见java day18-19的学习笔记

三、分类

数据结构有很多种,一般来说,按照数据的逻辑结构对其进行简单的分类,包括线性结构和非线性结构两类。

1.线性结构

简单地说,线性结构就是表中各个结点具有线性关系。如果从数据结构的语言来描述,线性结构应该包括如下几点:

1、线性结构是非空集。

2、线性结构有且仅有一个开始结点和一个终端结点。

3、线性结构所有结点都最多只有一个直接前趋结点和一个直接后继结点。

线性表就是典型的线性结构,还有栈、队列和串等都属于线性结构。 

2.非线性结构

简单地说,非线性结构就是表中各个结点之间具有多个对应关系。如果从数据结构的语言来描述,非线性结构应该包括如下几点:

1、非线性结构是非空集。

2、非线性结构的一个结点可能有多个直接前趋结点和多个直接后继结点。

在实际应用中,数组、广义表、树结构和图结构等数据结构都属于非线性结构。

JAVA day16、17 数据结构(栈、队列、数组、链表、红黑树)相关推荐

  1. Java集合常见数据结构-栈/队列/数组/链表/红黑树

    数组 链表 红黑树

  2. 常见的数据结构:栈 队列 数组 链表 红黑树——List集合 _ HashSet集合、可变参数 collections集合 Map集合

    2021-06-07复习java 一.常见的数据结构 栈(先进后出) 队列 数组 链表 红黑树 二.List集合_介绍&常用方法 ArrayList集合 Linkedlist集合 三.Hash ...

  3. 【Java8】堆栈/队列/数组/链表/红黑树,List/set子接口,hashcode/hashset,Map/内部接口,/统计字符个数,debug,斗地主,Collections,TreeSet

    文章目录 1.堆栈/队列/数组/链表:数据结构即计算机组织管理数据的方式,堆栈指的是内存图中的栈,不是堆 2.红黑树:二查,二查平,二查平1倍 3.List子接口:集合,IndexOutOfBound ...

  4. 常见数据结构-栈-队列-数组-链表-哈希表

    数据结构   数据结构是计算机存储.组织数据的方式.是指相互之间存在一种或多种特定关系的数据元素的集合   通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率 持续更新,学一个记一个- 栈 ...

  5. 存数组元素的个数_HashMap1.8之后为什么要采用数组+链表+红黑树的储存方式?

    HashMap概述 HashMap是基于Map接口实现的,采取(key,value)的储存方式.其中key和value可以为空,但是key不能重复.下面我们来详细解读一下HashMap的底层实现原理. ...

  6. Java开发 - 树(二叉树,二叉排序树,红黑树)

    目录 前言 你好,认识一下,我是树 二叉树与二叉排序树 二叉排序树特点 为什么说二叉排序树查询效率要高于链表呢? 元素的类型 比较器 手写二叉排序树 定义一棵二叉树 增加元素 查询元素 修改元素 删除 ...

  7. Android技术栈(五)HashMap(包括红黑树)与ArrayMap源码解析

    1 总览 本文会对 Android 中常用HashMap(有红黑树)和ArrayMap进行源码解析,其中 HashMap 源码来自 Android Framework API 28 (JDK=1.8) ...

  8. 栈,队列和链表三者之间的关系与区别

    最近一直在学习算法,刷算法题,但是自从大学毕业以来,数据结构的知识都还给老师了,只会个数组,所以前期刷的题目也都是有关数组的 最近跟着小册重学了一遍数据结构,今天就记录一下栈,队列和链表三者之间的关系 ...

  9. java 二叉树 红黑树_常见数据结构(二)-树(二叉树,红黑树,B树)

    常见数据结构(二)-树(二叉树,红黑树,B树) 标签: algorithms [TOC] 本文介绍数据结构中几种常见的树:二分查找树,2-3树,红黑树,B树 写在前面 本文所有图片均截图自course ...

  10. 【数据结构和算法05】 红-黑树(转发)

    2019独角兽企业重金招聘Python工程师标准>>> [数据结构和算法05] 红-黑树(看完包懂~) 置顶 2016年04月13日 15:50:25 eson_15 阅读数:526 ...

最新文章

  1. sklearn与pytorch模型的保存与读取
  2. 5.5 SVM补充-机器学习笔记-斯坦福吴恩达教授
  3. hdu 1692(枚举+剪枝)
  4. java安全编码指南之:输入注入injection
  5. SAP UI5 sap.viz.ui5.controls.VizFrame 的 aggregation 之一:dataset
  6. TQ210——核心板和底板
  7. 链表插入功能实现演示
  8. php excel列增加_PHP 高性能 Excel 扩展 1.2.7 发布
  9. TMS320C55x的寄存器
  10. windows下的nc下载地址
  11. QT安装遇到的问题及解决
  12. Ubuntu系统安装ghostscript seq2logo
  13. ACS712 电流传感器
  14. Java-图片处理 Gif转Jpg
  15. 【Buzz】简介及第一个案例
  16. 钉钉如何实现原笔迹手写签批
  17. vue + echarts 以山西地图为例
  18. 小程序分账系统是什么?能解决二清吗?
  19. Python 英文的月份转数字及数字转英文
  20. python数据处理系列之读写csv数据

热门文章

  1. mysql event 变量_DQL--select和MySQL的Event
  2. Python办公自动化 - 3 Excel办公自动化
  3. Express入门 模板引擎hbs 服务端渲染
  4. el-table使用图片实例代码
  5. 竞斗云2.0刷机-刷原厂固件
  6. 编译速度谁“最快”?25岁的 C++Builder 还能打
  7. 云智慧完成D3轮6000万美元融资,继续领跑智能运维市场
  8. 刚发布!开发者调查报告:机器学习/深度学习算法工程师急缺
  9. Uber首位App开发者离职自述:我们如何从3人小作坊变成大公司
  10. 这五个有用的 CSS 属性完全被我忽视了