数据结构:计算机存储、组织数据的方式,它用来反映一个数据的内部构成。
数据:信息的载体,是能够被计算机识别、存储、计算(处理)的符号集合,是计算机处理对象的总称。
数据含义在计算机语言中,十分广泛,除了通常使用的数字、字符串以外,任何能输入到并能被计算机处理的符号都可称为数据。
例如,声音,图片等。
数据元素:也称节点,组成数据的基本单位。可以由若干个数据项(也称字段、域、属性)组成。
例如,短信箱中的一条短信。
数据项:数据的最小单位,具有原子性,不可分割。
例如,一个联系人中的姓名和手机号等。
数据对象:具有相同特征的数据元素的集合,是数据的子集。
例如,短信箱,通讯录等
数据结构:逻辑结构 + 存储结构 + 数据运算
1.逻辑结构:从逻辑关系上描述数据,与数据的存储(内存中的存储位置,存储方式等)无关,且独立于语言。
2.存储结构:也称物理结构,指数据元素及其关系在计算机存储式如何表示,依赖语言。
3.数据运算:通常定义在逻辑结构上,每种逻辑结构都有一个运算的集合,但运算的具体实现要在存储结构上进行。
例如,数据对象的增删改查。
逻辑结构按数据元素之间的相互关系分为线性结构和非线性结构
1.线性结构
有且只有一个开始节点和一个终端节点,并且所有节点最多只有一个直接前驱和一个直接后继节点。
2.非线性结构
一个节点可能有多个直接前驱和直接后继节点。常见的非线性结构,树和图。
算法:为求解一个问题需要遵循的、被清晰地指定的简单指令的集合。通常以某一个数据集合作为输入,执行完一组特定的指令后,返回唯一的数据集合作为输出。
特点:
1.用待处理问题的信息作为输入数据。
2.对一个既定的合法输入,多次执行同一算法,总是返回同一个结果(出随机算法除外)。
3.算法中的指令都是可行的,即每个指令都可实现,并在有限的时间内完成。
4.算法中的指令数量有限,即在有限的时间内,算法可以正确结束。
5.算法执行完毕,能够输出正确的数据集合
算法是一个指令集和,包括控制结构指令和操作指令。即,算法是循环、跳转、判断指令、和数据的操作指令的集合。
算法分析:判断算法的执行效率。复杂度是判断算法优劣的标准,分为时间复杂度和空间复杂度。
1.时间复杂度:算法执行的时间长短
2.空间复杂度:算法在执行过程中所要占用的存储空间。它是额外消耗的存储空间,并不包括算法加载占用的存储空间。越复杂,算法越差。
线性数据结构:线性表、栈、队列等
非线性数据结构:树、图等
============线性表============
线性表:
1.数据元素之间是一对一关系
2.以字符串、数组、栈、队列等形式使用
特点:
1.有且只有一个开始节点和一个终端节点
2.内部节点均有且一个直接前驱和直接后继节点
3.均匀性:不同线性表的数据元素可以多样,但是同一个线性表的数据元素必定是相同的类型
4.有序性:数据元素在线性表中的位置只取决于序列,数据元素间的相对位置是线性的
5.线性表具有增删改查操作。如果需要自定义线性表操作,那么一定要先定义线性表操作的接口,然后在接口中定义线性表的基本操作
线性表的存储的数据在结构中的相对位置是随机的,即和数据的关键字不存在确定的关系,在结构中查找一条数据时,需要进行一系列和关键字做比较的动作。
范例:
1 public interface LinearList { 2 // 判断线性表是否为空 3 public boolean isEmpty(); 4 // 返回线性表的长度 5 public int size(); 6 // 返回指定索引为index的对象 7 public Object get(int index); 8 // 用指定元素替换线性表中指定位置的元素 9 public void set(int index,Object element); 10 // 在线性表的指定位置插入指定元素 11 public Boolean add(int index,Object element); 12 // 在线性表的末尾插入指定元素 13 public Boolean add(Object element); 14 // 删除线性表中指定位置的元素 15 public Object remove(int index); 16 // 清空线性表 17 public void clear(); 18 }
存储方式:
1.顺序存储:用一组连续的内存单元依次存放数据元素,数据元素在内存中的物理储存次序和在线性表中的逻辑次序相同。(数组)
优点:存储密度大。因为存储单位的位置是连续的,几乎不浪费空间。
缺点:插入,删除等不方便。
2.链式存储:用一组地址分散的存储单元存储数据元素,逻辑上相邻的数据元素在物理位置不一定相邻。(单链表)
特点:
1.每个元素节点都有一个指针。(产生原因:存储单元地址是分散的,逻辑关系是连续的。它需要一个指针指向元素的后续节点的地址位置)
分类:
a.单链表:也称线性链表,有一个个节点链接而成。每个节点都有一个数据域(nodeValue)和指针域(next)。指针域指向下一个节点的内存存储地址。
b.循环链表:在单链表的基础上,将表尾节点的指针域指向表头节点,整个链表形成环状结构。
c.双链表:可同时向前和向后查找数据元素的单链表。每个节点都有一个数据域和previous和next指针域,分别指向直接前驱节点和直接后继节点。
范例:
1.顺序存储,实现线性表操作的接口LinearList - SequenceList
1 public class SequenceList implements LinearList { 2 3 // 声明对象数组 4 private Object[] slist; 5 // 声明线性表的长度 6 private int size; 7 8 /** 9 * 调用带参构造方法 10 */ 11 public SequenceList() { 12 this(10); 13 } 14 15 public SequenceList(int length) { 16 if (length <= 0) { 17 this.slist = new Object[10]; 18 } 19 this.slist = new Object[length]; 20 size = 0; 21 } 22 23 @Override 24 public boolean isEmpty() { 25 if (size == 0) { 26 return true; 27 } else { 28 return false; 29 } 30 31 } 32 33 @Override 34 public int size() { 35 return size; 36 } 37 38 @Override 39 public Object get(int index) { 40 checkIndex(index); 41 return (Object)slist[index]; 42 } 43 44 @Override 45 public void set(int index, Object element) { 46 checkIndex(index); 47 slist[index] = element; 48 49 } 50 51 @Override 52 public Boolean add(int index, Object element) { 53 checkIndex(index); 54 if (size == slist.length) { 55 Object[] temp = slist; 56 this.slist = new Object[temp.length * 2]; 57 for (int j = 0; j < temp.length; j++) { 58 slist[j] = temp[j]; 59 } 60 } 61 for (int i = size - 1; i >= index; i--) { 62 slist[i + 1] = slist[i]; 63 } 64 slist[index] = element; 65 size++; 66 return true; 67 } 68 69 @Override 70 public Boolean add(Object element) { 71 return add(size,element); 72 } 73 74 @Override 75 public Object remove(int index) { 76 checkIndex(index); 77 Object old = (Object)slist[index]; 78 for (int i = index; i < size - 1; i++) { 79 slist[i] = slist[i + 1]; 80 } 81 slist[size--] = null; 82 return old; 83 } 84 85 @Override 86 public void clear() { 87 if (size != 0) { 88 for (int i = 0; i < size; i++) { 89 slist[i] = null; 90 } 91 size = 0; 92 } 93 94 } 95 96 /** 97 * @Description: 判断传入的索引值对于当前的线性表是否合法 98 * @param index 99 */ 100 public void checkIndex(int index) { 101 if (index >= size || index < 0) { 102 throw new IndexOutOfBoundsException("index" + index + "size" + size); 103 } 104 } 105 106 }
2.单链表
a.节点类 - Node
1 public class Node { 2 // 节点值 3 private Object nodeValue; 4 // 指针 5 private Node next; 6 7 public Node() { 8 nodeValue = null; 9 next = null; 10 } 11 12 /** 13 * 初始化节点值 14 * @param item 15 */ 16 public Node(Object item) { 17 nodeValue = item; 18 next = null; 19 } 20 21 /** 22 * 初始化节点值和指针 23 * @param item 24 * @param next 25 */ 26 public Node(Object item,Node next) { 27 nodeValue = item; 28 this.next = next; 29 } 30 31 public Object getNodeValue() { 32 return nodeValue; 33 } 34 35 public void setNodeValue(Object nodeValue) { 36 this.nodeValue = nodeValue; 37 } 38 39 public Node getNext() { 40 return next; 41 } 42 43 public void setNext(Node next) { 44 this.next = next; 45 } 46 }
b.SingleLinkedList
1 public class SingleLinkedList implements LinearList { 2 3 private Node head; 4 5 /** 6 * 初始化head为空 7 */ 8 public SingleLinkedList(){ 9 head = null; 10 } 11 12 /** 13 * 初始化head 14 */ 15 public SingleLinkedList(Node head){ 16 this.head = head; 17 } 18 19 @Override 20 public boolean isEmpty() { 21 return head == null; 22 } 23 24 @Override 25 public int size() { 26 int size = 0; 27 Node p = this.head; 28 while (p != null) { 29 size++; 30 p = p.getNext(); 31 } 32 return size; 33 } 34 35 @Override 36 public Object get(int index) { 37 checkIndex(index); 38 Node p = this.head; 39 for (int i = 0; i < index; i++) { 40 p = p.getNext(); 41 } 42 return (Object)p.getNodeValue(); 43 } 44 45 @Override 46 public void set(int index, Object element) { 47 checkIndex(index); 48 Node p = this.head; 49 for (int i = 0; i < index; i++) { 50 p = p.getNext(); 51 } 52 p.setNodeValue(element); 53 54 } 55 56 @Override 57 public Boolean add(int index, Object element) { 58 if (index < 0) { 59 throw new IndexOutOfBoundsException("index" + index); 60 } 61 if (head == null) { 62 head = new Node(element); 63 } else { 64 Node p = this.head; 65 if (index == 0) { 66 this.head = new Node(element,p); 67 } else { 68 int i = 0; 69 while (p.getNext() != null && i < index - 1) { 70 i++; 71 p = p.getNext(); 72 } 73 p.setNext(new Node(element,p.getNext())); 74 } 75 } 76 return false; 77 } 78 79 @Override 80 public Boolean add(Object element) { 81 return add(Integer.MAX_VALUE, element); 82 } 83 84 @Override 85 public Object remove(int index) { 86 checkIndex(index); 87 Object old = null; 88 Node p = this.head; 89 if (index == 0) { 90 old = (Object)this.head.getNodeValue(); 91 head = p.getNext(); 92 p = null; 93 } else { 94 int i = 0; 95 while (p.getNext() != null && i < index - 1) { 96 i++; 97 p = p.getNext(); 98 } 99 Node temp = p.getNext(); 100 old = (Object)temp.getNodeValue(); 101 p.setNext(temp.getNext()); 102 temp = null; 103 } 104 return old; 105 } 106 107 @Override 108 public void clear() { 109 head = null; 110 111 } 112 113 public void checkIndex(int index) { 114 if (index < 0 || index > this.size() - 1) { 115 throw new IndexOutOfBoundsException("index" + index); 116 } 117 } 118 119 }
线性表的顺序查找
除了增删查改等基本操作外,还有一些常见的操作,例如从线性表中获取数据的位置
范例:有一个线性表,表中数据域存储A-G7个大写英文字母,查找“F”的位置。
1.查找类
1 /** 2 * @Description: 查找类 3 * @author Ivy 4 */ 5 public class Search { 6 public static int search_seq(LinearList ST,String key) { 7 int i = 0; 8 while (!ST.get(i).equals(key)) { 9 i++; 10 } 11 return i; 12 } 13 }
2.测试类
1 public class Test { 2 public static void main(String[] args) { 3 LinearList ST = new SequenceList(); 4 String key = "F"; 5 ST.add("A"); 6 ST.add("B"); 7 ST.add("C"); 8 ST.add("D"); 9 ST.add("E"); 10 ST.add("F"); 11 ST.add("G"); 12 int i = Search.search_seq(ST, key); 13 System.out.println("关键字F的位置:" + i); 14 } 15 }