恋上数据结构 链表(手写LinkedList+练习)
Posted 结构化思维wz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了恋上数据结构 链表(手写LinkedList+练习)相关的知识,希望对你有一定的参考价值。
LinkedList(链表)
动态数组有个明显的缺点:
动态数组可能会造成内存空间的大量浪费
能否用到多少内存就申请多少内存呢?链表就可以办到这一点,链表是一种链式存储的线性表,所有元素的内存地址不一定是连续的。
节点类(Node)
/**
* 节点类
*/
private static class Node<E>
/**
* 存储的元素
*/
E element;
/**
* 下一个节点
*/
Node<E> next;
/**
* 构造函数
*/
public Node(E element, Node<E> next)
this.element = element;
this.next = next;
接口设计
由于链表与动态数组可以抽象出共同的方法,所以我们可以实现接口来优化代码。
抽象接口之后创建对象的方法变为:
List<Interger> list = new LinkedList();
接口设计为:
package 链式结构;
public interface List<E>
static final int ELEMENT_NOT_FOUND = -1;
/**
* 清除所有元素
*/
void clear();
/**
* 元素的数量
* @return
*/
int size();
/**
* 是否为空
* @return
*/
boolean isEmpty();
/**
* 是否包含某个元素
* @param element
* @return
*/
boolean contains(E element);
/**
* 添加元素到尾部
* @param element
*/
void add(E element);
/**
* 获取index位置的元素
* @param index
* @return
*/
E get(int index);
/**
* 设置index位置的元素
* @param index
* @param element
* @return 原来的元素ֵ
*/
E set(int index, E element);
/**
* 在index位置插入一个元素
* @param index
* @param element
*/
void add(int index, E element);
/**
* 删除index位置的元素
* @param index
* @return
*/
E remove(int index);
/**
* 查看元素的索引
* @param element
* @return
*/
int indexOf(E element);
手写LinkedList
LinkedList
package 链式结构.linkedlist;
import org.w3c.dom.Node;
import 链式结构.List;
/**
* @ClassName: LinkedList
* @Description: 链表
* @author: wangz48
* @date: 2021-12-27 9:57
*/
public class LinkedList<E> implements List
/*==============成员变量================*/
/**
* 链表长度
*/
private int size;
/**
* 头结点
*/
private Node first;
/*===============构造方法===============*/
/**
* 默认无参构造,因为不需要传容量
*/
public LinkedList()
/*===============成员方法===============*/
/**
* 清空链表
* size = 0;
* first = null
*/
@Override
public void clear()
size = 0;
first = null;
@Override
public int size()
return size;
@Override
public boolean isEmpty()
return size == 0;
@Override
public boolean contains(Object element)
return indexOf(element) != ELEMENT_NOT_FOUND;
@Override
public void add(Object element)
add(size,element);
@Override
public Object get(int index)
Node<E> node = node(index);
return node.element;
@Override
public Object set(int index, Object element)
Node<E> node = node(index);
E old = node.element;;
node.element = (E) element;
return old;
/**
* 添加元素。需要找index-1的元素
* @param index
* @param element
*/
@Override
public void add(int index, Object element)
if (index == 0)
first = new Node<>(element, first);
else
//前一个节点
Node<E> preNode = node(index - 1);
//新节点
Node<E> node = (Node<E>) new Node(element, preNode.next);
//前一个节点指向新的
preNode.next = node;
//长度增加
size++;
private Node<E> node(int index)
rangeCheck(index);
Node<E> node = first;
for (int i = 0; i < index; i++)
node = node.next;
return node;
/**
* 获取前面的元素,用next指向index+1的节点
* @param index
* @return
*/
@Override
public Object remove(int index)
rangeCheck(index);
Node<E> node = first;
if (index == 0)
first = first.next;
else
Node<E> prevNode = node(index - 1);
prevNode.next = prevNode.next.next;
size--;
return node.element;
@Override
public int indexOf(Object element)
if (element == null)
Node<E> node = first;
for (int i = 0; i < size; i++)
if (node.element == null)return i;
node = node.next;
else
Node<E> node = first;
for (int i = 0; i < size; i++)
if (element.equals(node.element))return i;
node = node.next;
return ELEMENT_NOT_FOUND;
@Override
public String toString()
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("size=").append(size).append(",[");
Node<E> node = first;
for (int i = 0; i < size; i++)
if(i != 0)
stringBuilder.append(",");
stringBuilder.append(node.element);
node = node.next;
stringBuilder.append("]");
return stringBuilder.toString();
/*===============其他方法===============*/
/**
* 边界检查
*/
private void outOfBounds(int index)
throw new IndexOutOfBoundsException("Index"+index+",Size:"+size);
/**
* 权限检查
*/
private void rangeCheck(int index)
if (index < 0 || index >= size)
outOfBounds(index);
/**
* add检查索引越界
*/
private void rangeCheckForAdd(int index)
if (index < 0 || index > size)
outOfBounds(index);
/*===============节点内部类===============*/
/**
* 节点类
*/
private static class Node<E>
/**
* 存储的元素
*/
E element;
/**
* 下一个节点
*/
Node<E> next;
/**
* 构造函数
*/
public Node(E element, Node<E> next)
this.element = element;
this.next = next;
练习
1.删除链表中的节点
分析:
当前节点的值 = .next的值
当前节点的next= .next.next;
class Solution
public void deleteNode(ListNode node)
node.val = node.next.val;
node.next = node.next.next;
2.反转链表
递归解法
class Solution
public ListNode reverseList(ListNode head)
//返回条件
if(head == null || head.next == null)return head;
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
迭代法
class Solution
public ListNode reverseList(ListNode head)
if(head == null || head.next == null)return head;
ListNode newHead = null;
while(head != null)
ListNode tmp = head.next;
head.next = newHead;
newHead = head;
head = tmp;
return newHead;
以上是关于恋上数据结构 链表(手写LinkedList+练习)的主要内容,如果未能解决你的问题,请参考以下文章
从0开始手写ArrayList动态数组和LinkedList双向链表
从0开始手写ArrayList动态数组和LinkedList双向链表