java-----单链表
Posted 小鹿可可乐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java-----单链表相关的知识,希望对你有一定的参考价值。
单链表
1.单链表基本操作
链表是一个有序的列表
链表不同于数组,链表是以结点的形式存储,在物理空间上不一定连续
链表的每个结点的内部包含value(数据)域,next(指针)域,指针域指向下一个结点的位置
1.1代码
public class SingleLink<E extends Comparable<E>> implements List<E> {
private Node<E> head;
private Node<E> tail;//尾部 尾插的时间复杂度O(1)
private int size;
public SingleLink(){
this.head = null;//空链表
this.tail = null;
}
@Override
public void addHead(E value) {//O(1)
Node<E> node = new Node<>(value);
if(head ==null && tail == null){
head = node;
tail = node;
}else {
//新节点的next = head
node.next = head;
}
//更新新头节点位置
head = node;
size++;
}
@Override
public void addTail(E value) {//O(1)
//申请value节点
Node<E> node = new Node<>(value);
if(head==null ){//链表不存在有效节点
head = node;
tail = node;//唯一node 既是头又是尾
}else{
tail.next = node;
}
size++;
}
@Override
public void removeHead() {
if(head ==null){
return;
}
else if(size==1){//head.next = null 只有一个节点
tail=null;
}
head.value=null;
Node<E> p = head.next;//p只保存地址
head.next=null;
head=p;
size--;
}
@Override
public void removeTail() {
if(head == null){//链表为空
return;
}else if(size == 1){//一个节点
head.value=null;
head=null;
tail = null;
}else{//>=两个节点
//找链表尾巴前趋
Node<E> p =head;
for(;p.next.next==null;p=p.next){
;
}
p.next = null;
tail.value = null;//防止内存泄漏
tail = p;//更新尾巴指向
}
size--;
}
@Override
public void removeValue(E value) {
if(head == null){
return;
}else if(head.value.compareTo(value) == 0){
removeHead();
}else{
//找待删节点的前驱
Node<E> p= head;
for(;p.next.value.compareTo(value) != 0;p = p.next){
;
}
Node<E> q = p.next.next;
p.next.value = null;//防止内存泄漏
//p.next=q.next;
//q.next=null;q.value=null;
p.next.next = null;
p.next = q;
size--;
}
}
@Override
public boolean contains(E value) {
for(Node<E> p = head;p!=null;p = p.next){
if(p.value.compareTo(value) == 0){
return true;
}
}
return false;
}
@Override
public void change(E srcValue, E aimValue) {
for(Node<E> p = head;p!=null;p = p.next) {
if (p.value.compareTo(srcValue) == 0) {
p.value = aimValue;
}
}
}
@Override
public void show(){
for(Node<E> p = head;p!=null;p=p.next){
System.out.print(p.value+" ");
}
System.out.println();
}
public Node<E> getHead() {
return head;
}
public void setHead(Node<E> head) {
this.head = head;
}
public void setTail(Node<E> tail) {
this.tail = tail;
}
public Node<E> getTail() {
return tail;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
//Node类型
//当前类里边this以外,不用包含外部类对象引用
static class Node<T>{
T value;
Node<T> next;
public Node(T value) {
this.value = value;
}
}
}
2.单链表练习题
2.1 逆置单链表
/*
一、逆置单链表
*/
public void reverseLink(){
if(head == null || size == 1){
return;
}
Node<E> p=head;
Node<E> q=p.next;
Node<E> s=q.next;
head.next=null;//原来头节点->尾巴节点
while(q != null){
q.next=p;
p = q;
q = s;
if(s!=null) {
s = s.next;
}
}
tail = head;//新尾巴用原来head更新
head = p;//循环结束 p标志的使新头
}
2.2 假设两个链表相交,输出相交节点
//二、假设两个链表相交,输出相交节点
public Node<E> getMeetNode(SingleLinkTest<E> link){
//1.让长链表走差值步,长短链表一起向后遍历,
int curSize = size;
int linkSize = link.size;
int diff = curSize-linkSize;
Node<E> longLinkP = diff > 0 ? head : link.head;//longLinkP遍历长链表
Node<E> shortLinkP = diff > 0 ? link.head : head;
//长链表遍历差值步
diff = Math.abs(diff);//取绝对值
while(diff>0){
longLinkP = longLinkP.next;
diff--;
}
while(longLinkP != shortLinkP){
longLinkP = longLinkP.next;
shortLinkP = shortLinkP.next;
}
return longLinkP;
}
2.3 给定一个链表,删除指定节点,O(1)时间复杂度删除指定节点
//三、给定一个链表,删除指定节点,O(1)时间复杂度删除指定节点
public static <E extends Comparable<E>>boolean removeNode(SingleLink<E> link,SingleLink.Node node){
//参数安全检测
if(link == null || node == null){
return false;
}
if(node == link.getTail()){
link.removeTail();
}else{
node.value = node.next.value;//将当前节点node,下一个节点value赋值给当前节点
node.next = node.next.next;//删除node的下一个节点
}
link.setSize(link.getSize()-1);//size--
return false;
}
2.4两个有序单链表合并为一个有序单链表
//四、两个有序单链表合并为一个有序单链表
public void mergeLink(SingleLinkTest<E> link){//this link
if(link == null || head == null && link.head == null){
return;
}
if(this.head == null){
this.head = link.head;
this.tail = link.tail;
}
Node<E> p = this.head,q = link.head;
//this.head 更新 两个链表开始的头部value,谁小谁作为起始
this.head = this.head.value.compareTo(link.head.value)<0 ? this.head:link.head;
if(p == head){
p = p.next;
}else{
q = q.next;
}
Node<E> s = head;//新链表尾部 连接动作
while(p != null && q != null){
if(p.value.compareTo(q.value) < 0){
s.next = p;
p = p.next;
}else{
s.next = q;
s = q;//更新到链表尾巴
q = q.next;
}
}
if(p == null){
q = q.next;
}else{
p = p.next;
}
while(s.next != null){
s = s.next;
}
this.tail = s;
}
2.5 判断链表是否有环,并输出相交节点
//五、判断链表是否有环,并输出相交节点
private Node<E> isLoop0(){
Node<E> fast = head,slow = head;
do{
if(fast == null || fast.next == null){
return null;
}
fast = fast.next.next;
slow = fast.next;
}while(fast != slow);
return fast;
}
public boolean isLoop(){
return !(isLoop0() == null);
}
//环的入口点
public Node<E> loopNode(){
Node<E> fast = isLoop0();//获得相遇点
Node<E> p = head,q = fast;
while(p != q){
p = p.next;
q = q.next;
}
return p;
}
今天也要好好学习呀~
以上是关于java-----单链表的主要内容,如果未能解决你的问题,请参考以下文章