线性数据结构
1.动态数组
2.栈
3.队列
底层都是依托静态数组:靠resize解决固定容量的问题
链表:真正的动态数据结构
一:链表
优点:不需要处理固定容量的问题,真正的动态
缺点:丧失了随机访问能力
二:创建Node
//使用内部类--创建结点
class Node<T> {
T data;//存放数据
Node next;
public Node(T data, Node head) {
this.data = data;
this.next = next;
}
public Node(T data) {
this.data=data;
this.next=null;
}
}
//重写tostring 打印链表
@Override
public String toString() {
Node curNode = this.head;
StringBuilder sb = new StringBuilder();
while (curNode != null) {
sb.append(curNode.data + "--->");
curNode = curNode.next;
}
sb.append("null");
return sb.toString();
}
三:插入操作
3.1插入操作
//在任意位置添加
public void add(int index,T data){
//判断是否有效
if (index<0||index>this.size){
throw new IllegalArgumentException("index is invalid");
};
//1.创建一个结点
Node node=new Node(data);
//特殊处理1:索引为0;
if(index==0){
this.head=new Node(data,this.head);
this.size++;
return;
}
//2.找前驱结点,从头开始找,让索引引动index-1
Node pre=this.head;
for(int i=0;i<index;i++){
pre=pre.next;
}
//3.开始结点的连接
node.next=pre.next;
pre.next=node;
this.size++;
}
(1)在表头插入结点
public void addHead(T data) {
add(0,data);
}
(2)表尾插入
四:创建带虚拟头结点的链表以及相关属性
//链表相关的属性与方法
private Node head;//链表的头
private int size;//表示链表中多少个结点
public LinkedList() {
//创建一个虚拟头结点
Node dummyHead=new Node(Integer.MIN_VALUE);
this.head = null;
this.size = 0;
}
在任意位置插入结点
五:查
5.1查头
public Optional getFirst(){
if(this.head.next==null){
return Optional.empty();
}
return Optional.ofNullable(this.head.next.data);
}
5.2查尾
public Optional getLast(){
if(this.head.next==null){
return Optional.empty();
}
Node curNode=this.head;
while(curNode.next!=null){
curNode=curNode.next;
}
return Optional.of(curNode.data);
}
六:删除
6.1 任意位置的删除
public T remove(int index){
if(index<0||index>this.size){
throw new IllegalArgumentException("");
}
Node<T> pre=this.head;
int i=0;
while(i<index){
pre=pre.next;
i++;
}
Node<T> delNode=pre.next;
pre.next=delNode.next;
delNode.next=null;
this.size--;
return delNode.data;
}
6.2根据值去删除使用虚拟头结点
//根据值去删除使用虚拟头结点
public int removebyValue(T val) {
int count = 0;
//定义前驱结点
Node<T> pre = this.head;
while (pre.next != null) {
Node curNode = pre.next;
if (curNode.data.equals(val)) {
pre.next = pre.next.next;
curNode.next = null;
this.size--;
count++;
} else {
pre = pre.next;
}
}
return count;
}
6.3根据值删除不使用虚拟头结点
//根据值去删除(不用头结点)
public int removebyValue2(T val) {
int count = 0;
//定义前驱结点
Node<T> realHead=this.head.next;
while(realHead!=null&& realHead.data.equals(val)){
realHead=realHead.next;
this.size--;
count++;
}
//假设头结点不是要删除的结点
Node pre=realHead;
while(pre.next==null) {
Node<T> delNode = pre.next;
if (delNode.equals(val)) {
pre.next=delNode.next;
delNode.next=null;
this.size--;
count++;
}else{
pre=pre.next;
}
}
return count;
}
完整代码如下
public class LinkedList<T> {
//使用内部类--创建结点
class Node<T> {
T data;//存放数据
Node next;
public Node(T data, Node head) {
this.data = data;
this.next = next;
}
public Node(T data) {
this.data = data;
this.next = null;
}
}
//链表相关的属性与方法
private Node head;//链表的头
private int size;//表示链表中多少个结点
public LinkedList() {
//创建一个虚拟头结点
Node dummyHead = new Node(Integer.MIN_VALUE);
this.head = null;
this.size = 0;
}
//判断链表是否为空
public boolean isEmpty() {
return this.size == 0;
}
//在链表中添加结点
//在任意位置添加
public void add(int index, T data) {
//判断是否有效
if (index < 0 || index > this.size) {
throw new IllegalArgumentException("index is invalid");
}
;
//1.创建一个结点
Node node = new Node(data);
//特殊处理1:索引为0;
if (index == 0) {
this.head = new Node(data, this.head);
this.size++;
return;
}
//2.找前驱结点,从头开始找,让索引引动index-1
Node pre = this.head;
for (int i = 0; i < index; i++) {
pre = pre.next;
}
//3.开始结点的连接
node.next = pre.next;
pre.next = node;
this.size++;
}
//在头部添加
public void addHead(T data) {
add(0, data);
}
// 在尾部添加
public void addTail(T data) {
add(this.size, data);
}
// 得到任意位置的结点
public T get(int index) {
if (index < 0 || index >= this.size) {
throw new IllegalArgumentException();
}
Node<T> curNode = this.head.next;
int i = 0;
while (i < index) {
curNode = curNode.next;
}
return curNode.data;
}
public Optional getFirst() {
if (this.head.next == null) {
return Optional.empty();
}
return Optional.ofNullable(this.head.next.data);
}
public Optional getLast() {
if (this.head.next == null) {
return Optional.empty();
}
Node curNode = this.head;
while (curNode.next != null) {
curNode = curNode.next;
}
return Optional.of(curNode.data);
}
public int getsize() {
return this.size;
}
//从链表头部删除
public T removeHead() {
if (this.isEmpty()) {
return null;
}
Node<T> delNode = new Node(this.head.next);
this.head.next = delNode.next;
delNode.next = null;
return delNode.data;
}
public T removeTail() {
if (this.isEmpty()) {
return null;
}
Node<T> pre = this.head;
while (pre.next == null) {
pre = pre.next;
}
Node<T> delNode = pre.next;
pre.next = delNode.next;
delNode.next = null;
this.size--;
return delNode.data;
}
// 删除任意位置的结点
public T remove(int index) {
if (index < 0 || index > this.size) {
throw new IllegalArgumentException("");
}
Node<T> pre = this.head;
int i = 0;
while (i < index) {
pre = pre.next;
i++;
}
Node<T> delNode = pre.next;
pre.next = delNode.next;
delNode.next = null;
this.size--;
return delNode.data;
}
//根据值去删除使用虚拟头结点
public int removebyValue(T val) {
int count = 0;
//定义前驱结点
Node<T> pre = this.head;
while (pre.next != null) {
Node curNode = pre.next;
if (curNode.data.equals(val)) {
pre.next = pre.next.next;
curNode.next = null;
this.size--;
count++;
} else {
pre = pre.next;
}
}
return count;
}
//根据值去删除(不用头结点)
public int removebyValue2(T val) {
int count = 0;
//定义前驱结点
Node<T> realHead=this.head.next;
while(realHead!=null&& realHead.data.equals(val)){
realHead=realHead.next;
this.size--;
count++;
}
//假设头结点不是要删除的结点
Node pre=realHead;
while(pre.next==null) {
Node<T> delNode = pre.next;
if (delNode.equals(val)) {
pre.next=delNode.next;
delNode.next=null;
this.size--;
count++;
}else{
pre=pre.next;
}
}
return count;
}
// 重写tostring 打印链表
@Override
public String toString() {
Node curNode = this.head.next;
StringBuilder sb = new StringBuilder();
while (curNode != null) {
sb.append(curNode.data + "--->");
curNode = curNode.next;
}
sb.append("null");
return sb.toString();
}
//从链表中查找指定元素是否存在
public boolean contains(T data) {
//遍历链表头结点不能动
Node curNode = this.head.next;
while (curNode.data == data) {
if (curNode.data.equals(data))
return true;
}
return false;
}}
快自己试试优化下代码吧