一、数据结构
数据结构是计算机存储、组织数据的方式
1、集合
数据结构中的元素之间除了“同属一个集合” 的相互关系外,别无其他关系;
2、线性结构
数据结构中的元素存在一对一的相互关系;
3、树形结构
数据结构中的元素存在一对多的相互关系;
4、图形结构
数据结构中的元素存在多对多的相互关系
二、为什么要引入链表
1)数组是很有用的数据结构,但是有两个局限:
1.若改变数据的大小就需要创建一个新数组并从原数组中拷贝所有数据至新数组
2.数组数据在内存中依次连续存储,向数组中插入一项要移动数组中其他数据
2)链表这种数据结构是使用指针(即引用)将存储数据元素的那些单元依次串联在一起
这种方法避免了在数组中用连续的单元存储元素的缺点,因而在插入或者删除时不再需要移动元素来腾出空间或填补空缺。
三、链表定义逻辑
需要作出的改变就是在每个单元中设置指针来表示表中元素之间的逻辑关系(前还是后)
四、定义链表节点:数据域和指针域(引用)
五、单链表
单链表的每个节点只有一个指向表中下一个节点的指针。第一个节点称为首节点,最后一个称为尾节点。尾节点的特征是next引用为null
六、单链表的特性
单链表的一个重要特性是只能通过前驱节点找到后续节点,因此在单链表中进行查找操作,只能从链表的首节点开始,通过每个节点的next引用来依次访问链表中的每个节点以完成相应的查找操作。而无法从后续节点找到前驱节点。
通常在单链表的最前面添加一个哑元节点,也称为头节点(Head)
注意:头节点有别于真正的首节点,头节点中不存储任何实质的数据对象,其next通常指向0位的元素。
七、双链表
双向链表是对单链表的扩充,以弥补单链表只能访问后续节点而不方便访问前驱节点的缺憾。
双向链表的结构是在单链表的节点结构上新增加一个域,用来指向直接前驱节点。
八、双链表的设计
除了需要实现Node接口定义的获取和设置数据域的两个方法以外,还需要提供对指向上下节点的指针的操作方法。为此提供四个方法,getNext()、setNext(Node node)、getPre()、setPre(Node node)
public class Node{
private String date;
private Node next;
private Node pre;
public Node(String date, Node next){this.date=date;this.next=next;}
public void setDate(String date){this.date = date;}
public String getDate(){return date;}
public void setNext(Node next){this.next = next;}
public Node getNext(){return next;}
public void setPre(Node pre){this.pre = pre;}
public Node getPre(){return pre;}
}
九、双链表的优点
1)在双链表中进行查找、删除、插入操作,既能从链表的首节点开始,也能从尾部开始
2)为使程序更简洁,通常在双链表的最前面和最后面各添加一个哑元节点。这样,由于首尾节点的存在,插入、删除操作都可被看作在双向链表中间某个节点的插入、删除;并且因为首尾节点的存在,整个链表永远不会为空,因此在插入和删除节点之后,也不用考虑链表由空变为非空或由非空变为空的情况下head和tail的指向问题,从而简化了问题。
自定义单链表:
package com.test.linked;
/**
* 结点类
*
* @author MHz
*
*/
public class Node<E> {
private Object data;
private Node<E> quote;// 引用时Node类型的
public Node() {
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Node<E> getQuote() {
return quote;
}
public void setQuote(Node<E> quote) {
this.quote = quote;
}
}
package com.test.linked;
/**
*
* @author MHz
*
*/
public class MyLinked<E> {
private int length;
private Node<E> head = new Node<E>();// 头结点
public void add(Object value) {// 链表尾插入
Node<E> node = new Node<E>();
node.setData(value);// 将数据存成Node
Node<E> current = head;
while (current.getQuote() != null) {// 寻找最后一个结点
current = current.getQuote();
}
current.setQuote(node);// 尾结点的引用存贮node
length++;
}
public void delet(int index) {// 删除某个位置的内容
Node<E> current = head;
int count = 0;
if (index < 0 || index >= length) {
try {
throw new Exception("下标越界!");
} catch (Exception e) {
e.printStackTrace();
}
return;
}
if (index == 0) {// 如果删除首结点
head.setQuote(head.getQuote().getQuote());
length--;
return;
}
while (count != index - 1) {
current = current.getQuote();
count++;
}
current.setQuote(current.getQuote());
length--;
}
public void insert(int index, Object value) {// 在某个位置插入内容
Node<E> current = head;
int count = 0;
Node<E> node = new Node<E>();
node.setData(value);
if (index < 0 || index >= length) {
try {
throw new Exception("下标越界!");
} catch (Exception e) {
e.printStackTrace();
}
return;
}
if (index == 0) {
Node<E> first = current.getQuote();// 首结点
current.setQuote(node);
node.setQuote(first);
length++;
return;
}
while (count != index) {// 哪里??
current = current.getQuote();
count++;
}
Node<E> firstNode = current.getQuote();// 保存当前index位置的引用
current.setQuote(node);
node.setQuote(firstNode);
length++;
}
public Object get(int index) {// 获取某个位置的内容
if (index < 0 || index >= length) {
try {
throw new Exception("下标越界!");
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
Node<E> current = head.getQuote();
int count = 0;// 从head开始数到index
while (count != index) {
current = current.getQuote();
count++;
}
return current.getData();
}
public int size() {
return length;
}
public void update(int index, Object value) {// 更新
int count = 0;
Node<E> current = head;
if (index < 0 || index >= length) {
try {
throw new Exception("下标越界!");
} catch (Exception e) {
e.printStackTrace();
}
return;
}
if (index == length) {
current.setData(value);
return;
}
while (count != index + 1) {
current = current.getQuote();
count++;
}
current.setData(value);
}
}
package com.test.linked;
/**
* 测试类
*
* @author MHz
*
*/
public class LinkedTest {
public static void main(String[] args) {
MyLinked<String> ml = new MyLinked<String>();
ml.add("aa");
ml.add("bb");
ml.add("cc");
ml.add("dd");
ml.insert(0, "ee");
for (int i = 0; i < ml.size(); i++) {
System.out.println(ml.get(i));
}
}
}