单链表所有基本操作,供自己闲时手机复习使用!
单向链表基本操作实现:
class LinkedNode{
public int data=0;
public LinkedNode next=null;
public LinkedNode(int data){
this.data=data;
}
}
public class LinkedList {
//链表的头结点(第一个节点),有了这个节点之后
//就可以根据next把所有的剩下元素都获取到
private LinkedNode head=null;
// 头插
public void addFirst(int e){
//先创建一个节点,并且让这个节点的值就是e
LinkedNode node=new LinkedNode(e);
//如果链表为空
if(this.head==null){
this.head=node;
return;
}
//如果链表不为空,那么直接把这个节点放在链表最开始的位置
node.next=head;
this.head=node;
return;
}
// 尾插
public void addLast(int e) {
//同样先创建一个节点,让这个节点的值为e
LinkedNode node = new LinkedNode(e);
//如果链表为空的话
if (this.head == null) {
this.head = node;
return;
}
//如果链表不为空,那么需要找最后一个节点,即cur.next==null这个节点
LinkedNode cur = this.head;
//cur从头结点开始不断向后走,把每一次的next赋值给cur,
// 直到cur.next==null跳出while循环,得到的就是最后一个节点
while (cur.next != null) {
cur = cur.next;
}
//再把最后一个节点的值变成e
cur.next = node;
}
// 任意位置插入,第一个数据点为0号下标
public void addIndex(int index,int e) {
//同样的,先创建一个node,让值就是e
LinkedNode node=new LinkedNode(e);
//合法性校验,下标越界情况考虑,这时候需要知道整个链表的长度
int len = size();
if (index < 0 || index > len) {
return;//抛出一个越界异常更好
}
//如果刚好是0号下标插入,则相当于头插
if (index == 0) {
addFirst(e);
return;
}
//如果刚好是len号下标,相当于尾插
if (index == len) {
addLast(e);
return;
}
//一般情况,插在中间的话,需要找要插入位置的前一个节点即index-1的位置
LinkedNode prev = getIndexPos(index - 1);
//让node获取到前一个节点的指向
node.next = prev.next;
//让前一个节点指向node,就完成了node的插入
prev.next = node;
}
// 获取下标为index节点的数据
private LinkedNode getIndexPos(int index) {
LinkedNode cur = this.head;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
return cur;
}
// 获取链表的长度
public int size(){
int size=0;
//链表遍历
for(LinkedNode cur=this.head;
cur!=null;cur=cur.next){
size++;
}
return size;
}
// 判断是否包含某个节点
public boolean contanins(int toFind){
for(LinkedNode cur=this.head;
cur!=null;cur=cur.next){
if(cur.data==toFind){
return true;
}
}
return false;
}
// 删除第一次出现关键字的节点
public void remove(int toRemove){
//空链表情况,删除失败
if(this.head==null){
return;//抛异常更好
}
//是否删除的是头结点
if(head.data==toRemove){
//如果删除了头结点,那么把下一个节点的数据指向赋值给头结点
//此时原来的头结点没有指向,会自然被GC回收掉
this.head=this.head.next;
return;
}
//一般情况,找要删除的节点的前一个节点
LinkedNode prev=searchPrev(toRemove);
//
LinkedNode nodeToRemove=prev.next;
prev.next=nodeToRemove.next;
}
// 删除所有出现关键字的元素
public void removeAllKey(int toRemove){
//空链表
if(head==null){
return;
}
//非空情况下
//先处理后续节点,最后处理头结点
LinkedNode prev=head;
LinkedNode cur=head.next;
while(cur!=null){
if(cur.data==toRemove){
//cur对应的节点就必须要删掉
prev.next=cur.next; //删除cur指向的节点
cur=prev.next; //让cur继续指向prev的下一个节点
}else {
//cur对应的节点不需要删除
prev=cur;
cur=cur.next;
}
}
//处理头结点
if(this.head.data==toRemove){
this.head=this.head.next;
}
return;
}
//查找要删除节点的前一个位置
private LinkedNode searchPrev(int toRemove){
//空链表
if(this.head==null){
return null;
}
//从要删除的节点前一个开始循环,直到结束
LinkedNode prev=this.head;
while(prev.next!=null){
if(prev.next.data==toRemove){
return prev;
}
//把前一个节点的指向赋值给前一个节点
prev=prev.next;
}
return null;
}
// 清空链表
public void clear(){
this.head=null; //无引用指向,JVM自动判定为垃圾GC回收
}
// 打印链表
public void display(){
System.out.println("[");
for (LinkedNode node=this.head;
node!=null;node=node.next){
System.out.println(node.data);
if(node.next!=null){
System.out.println(", ");
}
}
System.out.println("]");
}
}
双向链表所有基本操作,供自己闲时手机复习使用!
双向链表基本操作实现:
class Node {
public int data;
public Node next;
public Node prev;
public Node(int data) {
this.data = data;
}
}
class DoubleList {
public Node head;//头
public Node last;//尾巴
public DoubleList() {
this.head = null;
this.last = null;
}
//头插法
public void addFirst(int data) {
//1、判断是否是第一次插入
//2、不是第一次插入
Node node = new Node(data);
if (head == null) {
head = node;
last = node;
} else {
node.next = node;
node.next.prev = node;
head.next = node;
}
}
//尾插法
public void addLast(int data) {
Node node = new Node(data);
Node last = null;
if (head == null) {
head = node;
last = node;
} else {
last.next = node;
node.prev = last;
last = node;
}
}
//任意位置插入
public void addIndex(int index, int data) {
if (index < 0 || index > size(head)) {
return;
}
if (index == 0) {
addFirst(data);
return;
}
if (index == size) {
addLast(data);
return;
}
Node node = new Node(data);
Node cur = getPos(index);
node.next = cur;
node.prev = cur.prev;
next.prev = node;
node.prev.next = node;
}
//链表的长度
public int size(Node head) {
int size = 0;
for (ListNode cur = head;
cur != null; cur = cur.next) {
size++;
}
return size;
}
// 找到下标为 index 对应的节点
public Node getPos(int index) {
if (index < 0 || index > size(head)) {
throw new IndexOutOfTheBoundException("index 位置不合法");
}
Node cur = head;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
return cur;
}
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key) {
Node node = find(key);
if (node == null) {
return false;
}
return true;
}
//遍历链表找值为key的结点
public Node find(int key) {
for (Node cur = head.next;
cur != head; cur = cur.next) {
if (cur.data == key) {
return cur;
}
}
return null;
}
//删除第一次出现关键字为key的节点
public void remove(int key) {
Node cur = this.head;
int oldData = -1;
while (cur != null) {
ListNode next = cur.next;
if (cur.data == key) {
oldData = cur.data;
if (cur == this.head) {
this.head = cur.next;
head.prev = null;
} else {
if (cur.next != null) {
cur.next.prev = cur.prev;
} else {
this.last = cur.prev;
}
cur.prev.next = cur.next;
}
return oldData;
}
cur = cur.next;
}
return oldData;
}
//删除所有值为key的节点
public void removeAllKey(int key) {
Node cur = this.head;
while (cur != null) {
if (cur.data == key) {
oldData = cur.data;
if (cur == this.head) {
head = cur.next;
if (this.head != null) {
cur.prev = null;
}
} else {
if (cur.next != null) {
cur.next.prev = cur.prev;
} else {
last = cur.prev;
}
cur.prev.next = cur.next;
}
}
cur = cur.next;
}
}
//打印双向链表
public void display() {
Node cur = this.head;
while (cur != null) {
System.out.print(cur.data + " ");
cur = cur.next;
}
System.out.println();
}
//清空双向链表
public void clear() {
Node cur = this.head;
Node curNext = cur.next;
while (cur != null) {
cur.next = null;
cur.prev = null;
cur = curNext;
}
this.head = null;
this.last = null;
}