1.什么是数据结构?
计算机组织与储存数据的一种逻辑结构。
常见的数据结构有数组、链表、散列表、队列(阻塞队列)、栈、二叉树、红黑树等等。
注:
任何软件都是按照一定流程(算法)对数据(数据放哪儿、如何放,就是数据结构)进行加工与处理的过程。数据结构是为了解决高效地存取数据的问题的。
2.双向循环链表
(1)什么是双向循环链表?
在这里插入图片描述
package list;
/**
* 双向循环链表
*/
public class LinkedList<E> {
//head用于存放头节点的引用
private Node head;
//size用于存放链表的长度 (或者说节点的个数)
private int size;
/**
* Node类用于描述链表中的一个节点,
* 其中data用于储存数据(元素),
* next和prev用于存放后继节点和前驱节点的引用
*
*/
class Node{
E data;
Node next;
Node prev;
Node(E e){
data = e;
}
}
/**
* 将元素添加到链表末尾
* @param e 要添加的元素
* @return 添加成功返回true
*/
public boolean add(E e){
//先将元素封装成节点
Node node = new Node(e);
//如果链表为空,新节点就为头节点
if (head==null){
head = node;
head.next = head;
head.prev = head;
//链表的长度加1
size++;
return true;
}
//找到尾节点
Node last = head.prev;
//将新节点添加到尾节点后面
last.next = node;
node.next = head;
head.prev = node;
node.prev = last;
size++;
return true;
}
//toString方法
public String toString(){
if (head==null){
return "[]";
}
StringBuilder str = new StringBuilder("[");
str.append(head.data);
Node node = head.next;
while (node!=head){
str.append(","+node.data);
node = node.next;
}
return str.append("]").toString();
}
/**
* 返回链表的长度
* @return
*/
public int size(){
return size;
}
/**
* 返回指定下标的元素
* @param index 下标
* @return 该下标对应位置的元素
*/
public E get(int index){
//判断下标是否越界
if (index<0 || index>=size){
throw new IndexOutOfBoundsException("下标越界异常");
}
//找到对应位置处的节点
Node node = getNode(index);
//返回该节点存放的数据(即元素)
return node.data;
}
//将get里面的获取节点的方法提取出来
private Node getNode(int index) {
Node node = head;
if (index <= size>>1){
for (int i=0;i<index;i++){
node = node.next;
}
}else {
for (int i=size;i>index;i--){
node = node.prev;
}
}
return node;
}
public E remove(int index){
if (index<0 || index>=size){
throw new IndexOutOfBoundsException("下标越界");
}
//先找到要删除的节点
Node node = getNode(index);
//如果链表长度为一,即只有一个节点,则该节点肯定是头节点,
//删除该节点之后,需要将head设置为null
if (size==1){
E e = head.data;
head = null;
size--;
return e;
}
//找到该节点的上一个(前驱)节点和下一个(后继)节点
Node next = node.next;
Node prev = node.prev;
//该节点的上一个节点的后继节点指针指向该节点的下一个元素
prev.next = next;
//该节点的下一个节点的前驱节点指针指向该节点的上一个元素
next.prev = prev;
//如果删除的是头节点,则其下一个节点成为头节点
if (index==0){
head = next;
}
size--;
return node.data;
}
public void add(int index,E e){
if (index<0 || index>size){
throw new IndexOutOfBoundsException("下标越界");
}
//如果下标等于链表的长度,则调用add方法即可
if (index==size){
add(e);
return;
}
//封装要添加的节点
Node node = new Node(e);
//找到该位置的原来的那个节点,作为新节点的下一个节点
Node next = getNode(index);
//找到该位置原来节点的上一个节点作为新节点的上一个节点
Node prev = next.prev;
//建立和新节点的关系
node.next = next;
node.prev = prev;
next.prev = node;
prev.next = node;
//如果插入的节点的index=0,则新节点就成为头节点了
if (index==0){
head = node;
}
size++;
}
}