表白网站制作软件,怎么样自己制作网页,东莞微网站建设,设计本家装当我们谈论数据结构时#xff0c;我们实际上在讨论一种组织和管理数据的方式。数据结构是计算机科学中非常重要的一部分#xff0c;它为我们提供了存储、检索和操作数据的方法。在数据结构中#xff0c;链表是一种基本且常用的数据结构#xff0c;它由一系列节点组成#…当我们谈论数据结构时我们实际上在讨论一种组织和管理数据的方式。数据结构是计算机科学中非常重要的一部分它为我们提供了存储、检索和操作数据的方法。在数据结构中链表是一种基本且常用的数据结构它由一系列节点组成节点之间通过指针相互连接。
在本博客中我们将深入探讨链表的原理、操作及其在实际应用中的重要性。无论您是初学者还是有一定经验的程序员了解链表的基本概念和高级应用都将对您的编程技能产生积极的影响。 目录
1、数据结构剖析
1.1 研究对象一数据间逻辑运算关系
1.2 研究对象二数据的存储结构或物理结构
1.2.1 顺序结构
1.2.2 链式结构
1.2.3 索引结构
1.2.4 散列结构
1.3 研究对象三运算结构
2、一维数组
2.1 数组的特点
2.2 自定义数组
3、链表
3.1 链表的特点
3.2 自定义链表
3.2.1 自定义单向链表
3.2.2 自定义双向链表
4、栈
4.1 栈的特点
4.2 Stack使用举例
4.3 自定义栈
5、队列 1、数据结构剖析
简单来说数据结构就是一种程序设计优化的方法论研究数据的逻辑结构和物理结构以及它们之间相互关系并对这种结构定义相应的运算目的是加快程序的执行速度、减少内存占用的空间。
1.1 研究对象一数据间逻辑运算关系
数据的逻辑结构指反映数据元素之间的逻辑关系而与数据的存储无关是独立于计算机的。 集合结构数据结构中的元素之间除了“同属一个集合” 的相互关系外别无其他关系。集合元素之间没有逻辑关系。 线性结构数据结构中的元素存在一对一的相互关系。比如排队。结构中必须存在唯一的首元素和唯一的尾元素。体现为一维数组、链表、栈、队列 树形结构数据结构中的元素存在一对多的相互关系。比如家谱、文件系统、组织架构 图形结构数据结构中的元素存在多对多的相互关系。比如全国铁路网、地铁图 1.2 研究对象二数据的存储结构或物理结构
数据的物理结构/存储结构包括数据元素的表示和关系的表示。数据的存储结构是逻辑结构用计算机语言的实现它依赖于计算机语言。
1.2.1 顺序结构 顺序结构就是使用一组连续的存储单元依次存储逻辑上相邻的各个元素。 优点 只需要申请存放数据本身的内存空间即可支持下标访问也可以实现随机访问。 缺点 必须静态分配连续空间内存空间的利用率比较低。插入或删除可能需要移动大量元素效率比较低 1.2.2 链式结构 不使用连续的存储空间存放结构的元素而是为每一个元素构造一个节点。节点中除了存放数据本身以外还需要存放指向下一个节点的指针。 优点不采用连续的存储空间导致内存空间利用率比较高克服顺序存储结构中预知元素个数的缺点。插入或删除元素时不需要移动大量的元素。 缺点需要额外的空间来表达数据之间的逻辑关系不支持下标访问和随机访问。 1.2.3 索引结构 除建立存储节点信息外还建立附加的索引表来记录每个元素节点的地址。索引表由若干索引项组成。索引项的一般形式是关键字地址。 优点用节点的索引号来确定结点存储地址检索速度快。 缺点 增加了附加的索引表会占用较多的存储空间。在增加和删除数据时要修改索引表因而会花费较多的时间。 1.2.4 散列结构 根据元素的关键字直接计算出该元素的存储地址又称为Hash存储。 优点检索、增加和删除结点的操作都很快。 缺点不支持排序一般比用线性表存储需要更多的空间并且记录的关键字不能重复。 1.3 研究对象三运算结构
施加在数据上的运算包括运算的定义和实现。运算的定义是针对逻辑结构的指出运算的功能运算的实现是针对存储结构的指出运算的具体操作步骤。 分配资源建立结构释放资源 插入和删除 获取和遍历 修改和排序 2、一维数组
2.1 数组的特点
在Java中数组是用来存放同一种数据类型的集合注意只能存放同一种数据类型。
//只声明了类型和长度
数据类型[] 数组名称 new 数据类型[数组长度];//声明了类型初始化赋值大小由元素个数决定
数据类型[] 数组名称 {数组元素1数组元素2......}
物理结构特点
1、申请内存一次申请一大段连续的空间一旦申请到了内存就固定了。 2、不能动态扩展(初始化给大了浪费给小了不够用)插入快删除和查找慢。 -3、存储特点所有数据存储在这个连续的空间中数组中的每一个元素都是一个具体的数据或对象所有数据都紧密排布不能有间隔。 2.2 自定义数组
class Array {private Object[] elementData;private int size;public Array(int capacity){elementData new Object[capacity];}/*** 添加元素* param value*/public void add(Object value){if(size elementData.length){throw new RuntimeException(数组已满不可添加);}elementData[size] value;size;}/*** 查询元素value在数组中的索引位置* param value* return*/public int find(Object value){for (int i 0; i size; i) {if(elementData[i].equals(value)){return i;}}return -1;}/*** 从当前数组中移除首次出现的value元素* param value* return*/public boolean delete(Object value){int index find(value);if(index -1){return false;}for(int i index;i size - 1;i){elementData[i] elementData[i 1];}elementData[size - 1] null;size--;return true;}/*** 将数组中首次出现的oldValue替换为newValue* param oldValue* param newValue* return*/public boolean update(Object oldValue,Object newValue){int index find(oldValue);if(index -1){return false;}elementData[index] newValue;return true;}/*** 遍历数组中所有数据*/public void print(){System.out.print({);for (int i 0; i size; i) {if(i size - 1){System.out.println(elementData[i] });break;}System.out.print(elementData[i] ,);}}
}//测试类
public class ArrayTest {public static void main(String[] args) {Array arr new Array(10);arr.add(123);arr.add(AA);arr.add(345);arr.add(345);arr.add(BB);arr.delete(345);arr.update(345,444);arr.print();}
} 3、链表
3.1 链表的特点 逻辑结构线性结构 物理结构不要求连续的存储空间 存储特点链表由一系列结点node链表中每一个元素称为结点组成结点可以在代码执行过程中动态创建。每个结点包括两个部分一个是存储数据元素的数据域另一个是存储下一个结点地址的指针域。 3.2 自定义链表
3.2.1 自定义单向链表
/*
单链表中的节点。
节点是单向链表中基本的单元。
每一个节点Node都有两个属性一个属性是存储的数据。另一个属性是下一个节点的内存地址。*/
public class Node {// 存储的数据Object data;// 下一个节点的内存地址Node next;public Node(){}public Node(Object data, Node next){this.data data;this.next next;}
}
/*
链表类(单向链表)*/
public class LinkE {// 头节点Node header;private int size 0;public int size(){return size;}// 向链表中添加元素的方法向末尾添加public void add(E data){//public void add(Object data){// 创建一个新的节点对象// 让之前单链表的末尾节点next指向新节点对象。// 有可能这个元素是第一个也可能是第二个也可能是第三个。if(header null){// 说明还没有节点。// new一个新的节点对象作为头节点对象。// 这个时候的头节点既是一个头节点又是一个末尾节点。header new Node(data, null);}else {// 说明头不是空// 头节点已经存在了// 找出当前末尾节点让当前末尾节点的next是新节点。Node currentLastNode findLast(header);currentLastNode.next new Node(data, null);}size;}/*** 专门查找末尾节点的方法。*/private Node findLast(Node node) {if(node.next null) {// 如果一个节点的next是null// 说明这个节点就是末尾节点。return node;}// 程序能够到这里说明node不是末尾节点。return findLast(node.next); // 递归算法}/*// 删除链表中某个数据的方法public void remove(Object obj){//略}// 修改链表中某个数据的方法public void modify(Object newObj){//略}// 查找链表中某个元素的方法。public int find(Object obj){//略}*/
} 3.2.2 自定义双向链表
/*
双向链表中的节点。*/
public class NodeE {Node prev;E data;Node next;Node(Node prev, E data, Node next) {this.prev prev;this.data data;this.next next;}
}
public class MyLinkedListE implements IterableE{private Node first; //链表的首元素private Node last; //链表的尾元素private int total;public void add(E e){Node newNode new Node(last, e, null);if(first null){first newNode;}else{last.next newNode;}last newNode;total;}public int size(){return total;}public void delete(Object obj){Node find findNode(obj);if(find ! null){if(find.prev ! null){find.prev.next find.next;}else{first find.next;}if(find.next ! null){find.next.prev find.prev;}else{last find.prev;}find.prev null;find.next null;find.data null;total--;}}private Node findNode(Object obj){Node node first;Node find null;if(obj null){while(node ! null){if(node.data null){find node;break;}node node.next;}}else{while(node ! null){if(obj.equals(node.data)){find node;break;}node node.next;}}return find;}public boolean contains(Object obj){return findNode(obj) ! null;}public void update(E old, E value){Node find findNode(old);if(find ! null){find.data value;}}Overridepublic IteratorE iterator() {return new Itr();}private class Itr implements IteratorE{private NodeE node first;Overridepublic boolean hasNext() {return node!null;}Overridepublic E next() {E value node.data;node node.next;return value;}}
}
自定义双向链表测试
public class MyLinkedListTest {public static void main(String[] args) {MyLinkedListString my new MyLinkedList();my.add(hello);my.add(world);my.add(null);my.add(null);my.add(java);my.add(java);my.add(atguigu);System.out.println(一共有 my.size());System.out.println(所有元素);for (String s : my) {System.out.println(s);}System.out.println(-------------------------------------);System.out.println(查找java,null,haha的结果);System.out.println(my.contains(java));System.out.println(my.contains(null));System.out.println(my.contains(haha));System.out.println(-------------------------------------);System.out.println(替换java,null后);my.update(java,JAVA);my.update(null,songhk);System.out.println(所有元素);for (String s : my) {System.out.println(s);}System.out.println(-------------------------------------);System.out.println(删除helloJAVA,nullatguigu后);my.delete(hello);my.delete(JAVA);my.delete(null);my.delete(atguigu);System.out.println(所有元素);for (String s : my) {System.out.println(s);}}
} 4、栈
4.1 栈的特点 栈Stack又称为堆栈或堆叠是限制仅在表的一端进行插入和删除运算的线性表。 栈按照先进后出(FILO,first in last out)的原则存储数据先进入的数据被压入栈底最后的数据在栈顶。每次删除退栈的总是删除当前栈中最后插入进栈的元素而最先插入的是被放在栈的底部要到最后才能删除。 核心类库中的栈结构有Stack和LinkedList。 Stack就是顺序栈它是Vector的子类。 LinkedList是链式栈。 体现栈结构的操作方法 peek()方法查看栈顶元素不弹出 pop()方法弹出栈 push(E e)方法压入栈 时间复杂度: 索引: O(n) 搜索: O(n) 插入: O(1) 移除: O(1)
4.2 Stack使用举例
public class TestStack {/** 测试Stack* */Testpublic void test1(){StackInteger list new Stack();list.push(1);list.push(2);list.push(3);System.out.println(list list);System.out.println(list.peek() list.peek());System.out.println(list.peek() list.peek());System.out.println(list.peek() list.peek());/*System.out.println(list.pop() list.pop());System.out.println(list.pop() list.pop());System.out.println(list.pop() list.pop());System.out.println(list.pop() list.pop());//java.util.NoSuchElementException
*/while(!list.empty()){System.out.println(list.pop() list.pop());}}/** 测试LinkedList* */Testpublic void test2(){LinkedListInteger list new LinkedList();list.push(1);list.push(2);list.push(3);System.out.println(list list);System.out.println(list.peek() list.peek());System.out.println(list.peek() list.peek());System.out.println(list.peek() list.peek());/*System.out.println(list.pop() list.pop());System.out.println(list.pop() list.pop());System.out.println(list.pop() list.pop());System.out.println(list.pop() list.pop());//java.util.NoSuchElementException
*/while(!list.isEmpty()){System.out.println(list.pop() list.pop());}}
} 4.3 自定义栈
public class MyStack {// 向栈当中存储元素我们这里使用一维数组模拟。存到栈中就表示存储到数组中。// 为什么选择Object类型数组因为这个栈可以存储java中的任何引用类型的数据private Object[] elements;// 栈帧永远指向栈顶部元素// 那么这个默认初始值应该是多少。注意最初的栈是空的一个元素都没有。//private int index 0; // 如果index采用0表示栈帧指向了顶部元素的上方。//private int index -1; // 如果index采用-1表示栈帧指向了顶部元素。private int index;/*** 无参数构造方法。默认初始化栈容量10.*/public MyStack() {// 一维数组动态初始化// 默认初始化容量是10.this.elements new Object[10];// 给index初始化this.index -1;}/*** 压栈的方法* param obj 被压入的元素*/public void push(Object obj) throws Exception {if(index elements.length - 1){//方式1//System.out.println(压栈失败栈已满);//return;//方式2throw new Exception(压栈失败栈已满);}// 程序能够走到这里说明栈没满// 向栈中加1个元素栈帧向上移动一个位置。index;elements[index] obj;System.out.println(压栈 obj 元素成功栈帧指向 index);}/*** 弹栈的方法从数组中往外取元素。每取出一个元素栈帧向下移动一位。* return*/public Object pop() throws Exception {if (index 0) {//方式1//System.out.println(弹栈失败栈已空);//return;//方式2throw new Exception(弹栈失败栈已空);}// 程序能够执行到此处说明栈没有空。Object obj elements[index];System.out.print(弹栈 obj 元素成功);elements[index] null;// 栈帧向下移动一位。index--;return obj;}// set和get也许用不上但是你必须写上这是规矩。你使用IDEA生成就行了。// 封装第一步属性私有化第二步对外提供set和get方法。public Object[] getElements() {return elements;}public void setElements(Object[] elements) {this.elements elements;}public int getIndex() {return index;}public void setIndex(int index) {this.index index;}
}5、队列 队列Queue是只允许在一端进行插入而在另一端进行删除的运算受限的线性表。 队列是逻辑结构其物理结构可以是数组也可以是链表。 队列的修改原则队列的修改是依先进先出FIFO的原则进行的。新来的成员总是加入队尾即不允许加塞每次离开的成员总是队列头上的不允许中途离队即当前最老的成员离队。