上一篇我们手动实现了单向循环链表,今天我们实现一个双向循环链表。
import java.util.Objects;
/**
* 简单实现双向循环链表,双向循环链表与单向循环链表的区别是
* 单向循环链表只能通过当前节点访问下一节点,
* 双向循环链表可以通过当前节点访问上个节点和下个节点
*/
public class MyDoubleCircleLink {
private int size;
Node head;
Node tail;
/**
* 在链表尾部插入一个元素
* @param data 要插入的数据
*/
public void add(Object data){
Node newNode = new Node(data);
if(head==null){
newNode.next = newNode;
newNode.prev = newNode;
head = tail = newNode;
}else{
tail.next = newNode;
newNode.next = head;
head.prev = newNode;
newNode.prev = tail;
tail = newNode;
}
size++;
}
/**
* 在链表头部插入一个元素
* @param data 要插入的数据
*/
public void addHead(Object data){
Node newNode = new Node(data);
if(head==null){
newNode.next = newNode;
newNode.prev = newNode;
head = tail = newNode;
}else{
tail.next=newNode;
newNode.next=head;
head.prev = newNode;
newNode.prev = tail;
head=newNode;
}
size++;
}
/**
* 在链表指定位置插入一个元素(有两种场景,一种是指定index,一种是指定data,可以做一个重载)
* @param index 指定下标
* @param data 要插入的数据
*/
public void insert(int index,Object data){
Node newNode = new Node(data);
if(index>=size||index<0){
throw new IndexOutOfBoundsException("给定的下标超出链表长度或格式不正确");
}else{
if(index==0){//在下标为零的位置插入,就是从头部插入
addHead(data);
}else{
Node temp=head;
for(int i = 0;i<index-1;i++){
temp = temp.next;
}
temp.next.prev = newNode;
newNode.next = temp.next;
temp.next = newNode;
newNode.prev = temp;
size++;
}
}
}
/**
* 在目标数据前面插入一个元素
* @param target 目标数据
* @param data 要插入的数据
*/
public void insert(Object target,Object data){
Node newNode = new Node(data);
if(Objects.equals(target,head.data)){
addHead(data);
return;
}else {
for (Node temp = head; temp.next != null; temp = temp.next) {
if (Objects.equals(target, temp.next.data)) {//这里的next可以控制元素插入到目标元素之前还是之后
newNode.next = temp.next;
temp.next = newNode;
size++;
return;
}
}
}
//throw new FindException("指定的目标数据不存在");
System.out.println("指定的目标数据不存在");
}
/**
* 从链表尾部删除一个元素
*/
public void deleteTail(){
for(Node temp = head; temp!=tail; temp=temp.next){
if(temp.next==tail){
temp.next=head;
head.prev = temp;
tail = temp;
size--;
return;
}
}
}
/**
* 从链表头部删除一个元素
*/
public void deleteHead(){
tail.next = head.next;
head.next.prev = tail;
head = head.next;
size--;
}
/**
* 从链表指定位置删除一个元素(两种场景,一种是删除指定下标位置的元素,一种是删除值为目标值的元素(只删第一次出现的位置))
* @param index 指定下标
*/
public void delete(int index){
if(index >= size||index <0 ){
throw new IndexOutOfBoundsException("给定的下标超出链表长度或格式不正确");
}else{
if(index==0){
deleteHead();
}else if(index == size-1){
deleteTail();
}else{
int i=0;
for(Node temp = head; temp!=tail; temp = temp.next){
if(i==index-1){
temp.next.next.prev = temp;
temp.next=temp.next.next;
size--;
return;
}
i++;
}
}
}
}
/**
* 删除值为data的元素(一次)
* @param data
*/
public void delete (Object data){
if(Objects.equals(data,head.data)){
deleteHead();
return;
}else {
for(Node temp = head; temp!=tail; temp = temp.next){
if (Objects.equals(data, temp.next.data)) {
if(temp.next==tail){
deleteTail();
return;
}else {
temp.next.next.prev = temp;
temp.next = temp.next.next;
size--;
return;
}
}
}
}
System.out.println("指定的目标数据不存在");
}
/**
* 修改链表中指定位置元素的值
* @param index 指定下标
* @param data 修改后的值
*/
public void update(int index,Object data){
if(index>=size||index<0){
throw new IndexOutOfBoundsException("指定下标超出列表长度或下标格式不正确");
}else if(index == 0){
head.data = data;
}else{
Node temp = head;
for(int i = 0;i<size;i++){
if(i==index-1){
temp.next.data = data;
}
temp = temp.next;
}
}
}
/**
* 获取链表指定位置元素的值
*
* @param index 指定下标
*/
public Object get(int index){
if(index>=size||index<0){
throw new IndexOutOfBoundsException("指定下标超出列表长度或下标格式不正确");
}else if(index == 0){
return head.data;
}else{
Node temp = head;
for(int i = 0;i<size;i++){
if(i==index-1){
return temp.next.data;
}
temp = temp.next;
}
}
return null;
}
public void print(){
Node tempNode=head;
while(tempNode!=tail){
System.out.println(tempNode.data);
tempNode = tempNode.next;
}
System.out.println(tail.data);
}
//获取链表元素个数
public int size(){
return size;
}
class Node{
Object data;
Node next;//下一节点
Node prev;//上一节点
Node(Object data){
this.data = data;
this.next = null;
this.prev = null;
}
}
}