目录
1.先建立一个接口SeqList,在其中定义方法,使用了泛型
2.实现一个类,DoubleLinkedList,其中有三个属性,
3.还有一个自定义的数据类型DoubleNode ,也有三个属性
4.让DoubleLinkedList实现SeqList接口,重写其所有方法,使用了泛型
1.先建立一个接口SeqList,在其中定义方法,使用了泛型
public interface SeqList<E>{
//尾插
void add(E element);
//指定位置添加元素
void add(int index, E element);
//删除指定索引元素
E remove(int index);
//删除指定元素第一次出现的
void removeElement(E element);
//删除所有该值元素
void removeAll(E elemnet);
//修改指定下标元素
E set(int index, E element);
//查寻指定下标元素
E get(int index);
//判断是否存在
boolean contains(E element);
//查询指定元素下标,第一次出现
int indexOf(E element);
}
2.实现一个类,DoubleLinkedList,其中有三个属性,
//保存结点的个数 private int size; //头节点 private DoubleNode head; //尾节点 private DoubleNode tail;
3.还有一个自定义的数据类型DoubleNode ,也有三个属性
//当前节点保存的数值 E val; //当前节点的前结点的地址 DoubleNode prev; //当前节点下一个结点的地址 DoubleNode next;
4.让DoubleLinkedList实现SeqList接口,重写其所有方法,使用了泛型
代码注释及方法的重写如下:
public class DoubleLinkedList<E> implements SeqList<E>{
//保存结点的个数
private int size;
//头节点
private DoubleNode head;
//尾节点
private DoubleNode tail;
private
class DoubleNode {
//当前节点保存的数值
E val;
//当前节点的前结点的地址
DoubleNode prev;
//当前节点下一个结点的地址
DoubleNode next;
//构造器
public DoubleNode() {
}
public DoubleNode(E val) {
this.val = val;
}
public DoubleNode(E val, DoubleNode prev, DoubleNode next) {
this.val = val;
this.prev = prev;
this.next = next;
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for(DoubleNode x = head; x != null; x = x.next){
sb.append(x.val).append("->");
if(x == tail){
sb.append("null");
}
}
return sb.toString();
}
//在链表尾部添加元素
@Override
public void add(E element) {
//创建一个新节点保存数据
DoubleNode node = new DoubleNode(element);
size++;
//判断是否为空
if(head == null){
head = node;
}else {
tail.next = node;
node.prev = tail;
}
tail = node;
}
//在链表头部添加元素
public void addFirst(E element){
//创建一个新的节点保存数据
DoubleNode node = new DoubleNode(element);
size++;
//判断是否为空
if(tail == null){
tail = node;
}else {
head.prev = node;
node.next = head;
}
head = node;
}
@Override
public void add(int index, E element) {
//判断是否为头尾节点
if(index == 0){
//头插
addFirst(element);
return;
}
if(index == size){
//尾插
add(element);
return;
}
//一定有前驱后继
//写一个方法找到在index的节点findNode
//找到下标为index的节点
DoubleNode next = findNode(index);
DoubleNode prev = next.prev;
DoubleNode node = new DoubleNode(element,prev,next);
//先连接左边
prev.next = node;
//在连接右边
next.prev = node;
size++;
}
//找到在index的节点并返回
private DoubleNode findNode(int index){
//下标合法
if(!rangeCheck(index)){
throw new IllegalArgumentException("index illeagal!!");
}
if(index == 0){
return head;
}
if(index == size-1){
return tail;
}
//先创建一个空节点
DoubleNode result = null;
//根据下标位置判断是从前寻找还是从后寻找
//012345
if(index < size /2){
//下标小于size的一半,从前往后找
result = head;
for(int i = 0; i < index; i++){
result = result.next;
}
}else {
//0123456789
result = tail;
for(int i = size-1; i > index; i--){
result = result.prev;
}
}
return result;
}
//判断下标是否合法的方法
private boolean rangeCheck(int index){
if(index < 0 || index >= size){
return false;
}
return true;
}
//按照下标删除节点
@Override
public E remove(int index) {
//判断下标是否合法
if(!rangeCheck(index)){
throw new IllegalArgumentException("index illeagal!!");
}
//判断是否是头尾节点
if(index == 0){
DoubleNode prev = head;
head = head.next;
size--;
return prev.val;
}
if(index == size-1){
DoubleNode prev = tail;
tail = tail.prev;
tail.next = null;
size--;
return prev.val;
}
//先找到需要删除的下标
DoubleNode node = findNode(index);
//找到其前驱
DoubleNode prev = node.prev;
//找到后继
DoubleNode next = node.next;
//先断左边
prev.next = next;
node.prev = null;
//右边
node.next = null;
next.prev = prev;
size--;
return node.val;
}
//删除指定元素
@Override
public void removeElement(E element) {
//遍历元素找到其下标
DoubleNode prev = head;
for(int i = 0; i < size; i++){
if(prev.val.equals(element)){
remove(i);
return;
}
prev = prev.next;
}
System.out.println("链表中没有该元素~");
}
//删除所有指定元素
@Override
public void removeAll(E elemnet) {
//防止删除元素过程中size的改变
//将size的值先保存下来
int len = size;
DoubleNode prev = head;
for (int i = 0; i < len; i++) {
DoubleNode next = prev.next;
if(prev.val.equals(elemnet)){
removeElement(elemnet);
}
prev = next;
}
}
//修改下标为index的元素值
@Override
public E set(int index, E element) {
//判断合法
if(!rangeCheck(index)){
throw new IllegalArgumentException("index illeagal~~");
}
//找到需要修改的节点
DoubleNode node = findNode(index);
node.val = element;
return node.val;
}
//上面的方法fingNode已经实现这个功能,这里就不再重复写
@Override
public E get(int index) {
return null;
}
//判断元素是否在链表中
@Override
public boolean contains(E element) {
DoubleNode prev = head;
for(int i = 0; i < size; i++){
if(prev.val.equals(element)){
return true;
}
prev = prev.next;
}
return false;
}
//查询第一个出现指定元素的下标
@Override
public int indexOf(E element) {
DoubleNode node = head;
for(int i = 0; i < size; i++){
if(node.val.equals(element)){
return i;
}
node = node.next;
}
System.out.println("链表中没有该元素哦~");
return -1;
}
}