java自制链表
简言
众所周知,java自身库是有包涵链表的,但是有的数据结构老师和算法老师可能会让学生自己写链表。这里就演示个简单的单链表和双链表,并实现链表的增删改基础功能。
理论
链表的话,可以先进先出,后进先出。可以把链表看成杯子,杯口就叫他它head,杯底叫tail
先进先出(head进tail出)
后进先出(head进head出)
实现
- 定义链表和节点
class LinkList{
private Node head;
private Node tail;
private int size;
}
class Node{
String value;
Node next;
public Node(String val){
this.value=val;
}
public Node(String val,Node next){
this.next=next;
this.value=val;
}
public Node(){}
}
- 增加节点
public void add(Node node){
if(this.head==null&&this.tail==null){
this.head=node;
this.tail=node;
}else{
node.next=this.head;
this.head=node;
}
size++;
}
public boolean addafter(Node nodeone,Node nodetwo){
Node pre=this.head;
while(pre.value!=nodeone.value){
pre=pre.next;
}
if (pre.value!=nodeone.value){
return false;
}
if(pre.next==null){
pre.next=nodetwo;
}else{
Node buffernode=pre.next;
pre.next=nodetwo;
nodetwo.next=buffernode;
}
return true;
}
由于加入节点是从head端加的且为单链表,所以第一个节点进来的时候tail就和第一个节点绑定了,后面除了删除tail节点会导致tail节点变更,不然后续操作tail节点都不会动。至于addafter方法,则为在链表中指定节点后面加入新节点,若指定节点在链表中不存在,则返回false,成功在指定节点添加返回true。
- 查找节点
public Node get(int index){
if(index>=this.size){
return null;
}
int virsize=this.size-1;
Node headadd=this.head;
while(virsize!=index){
headadd=headadd.next;
virsize--;
}
return headadd;
}
public int get(String value){
if (this.size<1){
return -1;
}
Node headadd=this.head;
int virsize=this.size-1;
while (!headadd.value.equals(value)&&headadd.next!=null) {
headadd=headadd.next;
virsize--;
}
if(!headadd.value.equals(value)){
return -1;
}else{
return virsize;
}
}
这里有两个get方法,第一个通过位置返回节点,第二个通过节点值返回位置。
- 删除节点
链表原型
public void deletefirst(){
if(this.head!=null){
if(this.head.next!=null){
this.head=this.head.next;
}else{
this.head=null;
this.tail=null;
}
this.size--;
}
}
public void deletelast(){
Node headadd=this.head;
if (headadd!=null) {
if (headadd.next!=null){
while (headadd.next.next!=null) {
headadd=headadd.next;
}
this.tail=headadd;
headadd.next=null;
}else{
this.head=null;
this.tail=null;
}
this.size--;
}
}
这里可以看出我们删除节点有两种方法。deletefirst是从原型图中的head端开始删除(由于我们这里是单链表,只需把head标向下移一位就删除顶部节点了)。deletelast则是从tail开删,所以在tail标上移一位过后,还需申明tail没有下一位节点。
测试链表
public class Tutorial {
public static void main(String[] args) {
LinkList list=new LinkList();
list.add(new Node("im first in"));
list.add(new Node("im second in"));
list.add(new Node("im third in"));
list.addafter(new Node("im first in"), new Node("im last in"));
list.printList();
list.deletelast();
list.printList();
System.out.println(list.get(2).value);
System.out.println(list.get("im second in"));
}
}
测试结果
完整代码
public class Tutorial {
public static void main(String[] args) {
LinkList list=new LinkList();
list.add(new Node("im first in"));
list.add(new Node("im second in"));
list.add(new Node("im third in"));
list.addafter(new Node("im first in"), new Node("im last in"));
list.printList();
list.deletelast();
list.printList();
System.out.println(list.get(2).value);
System.out.println(list.get("im second in"));
}
}
class Node{
String value;
Node next;
public Node(String val){
this.value=val;
}
public Node(String val,Node next){
this.next=next;
this.value=val;
}
public Node(){}
}
class LinkList{
private Node head;
private Node tail;
private int size;
public LinkList(Node head){
this.head=head;
}
public LinkList(){}
public void add(Node node){
if(this.head==null&&this.tail==null){
this.head=node;
this.tail=node;
}else{
node.next=this.head;
this.head=node;
}
this.size++;
}
public boolean addafter(Node nodeone,Node nodetwo){
Node pre=this.head;
while(pre.value!=nodeone.value){
pre=pre.next;
}
if (pre.value!=nodeone.value){
return false;
}
if(pre.next==null){
pre.next=nodetwo;
}else{
Node buffernode=pre.next;
pre.next=nodetwo;
nodetwo.next=buffernode;
}
this.size++;
return true;
}
public Node get(int index){
if(index>=this.size){
return null;
}
int virsize=this.size-1;
Node headadd=this.head;
while(virsize!=index){
headadd=headadd.next;
virsize--;
}
return headadd;
}
public int get(String value){
if (this.size<1){
return -1;
}
Node headadd=this.head;
int virsize=this.size-1;
while (!headadd.value.equals(value)&&headadd.next!=null) {
headadd=headadd.next;
virsize--;
}
if(!headadd.value.equals(value)){
return -1;
}else{
return virsize;
}
}
public void deletefirst(){
if(this.head!=null){
if(this.head.next!=null){
this.head=this.head.next;
}else{
this.head=null;
this.tail=null;
}
this.size--;
}
}
public void deletelast(){
Node headadd=this.head;
if (headadd!=null) {
if (headadd.next!=null){
while (headadd.next.next!=null) {
headadd=headadd.next;
}
this.tail=headadd;
headadd.next=null;
}else{
this.head=null;
this.tail=null;
}
this.size--;
}
}
@Override
public String toString(){
StringBuilder sbf=new StringBuilder();
Node node=this.head;
while(node!=null){
sbf.append(node.value);
node=node.next;
}
return sbf.toString();
}
public void printList(){
StringBuilder sbf=new StringBuilder();
Node node=this.head;
while(node!=null){
sbf.append(node.value);
sbf.append("=>");
node=node.next;
}
sbf.append("end");
System.out.println(sbf.toString());
}
}
结语
- 关于双链表
这是两个链表的底层(node)。也就是说双链表相较于单链表来讲,非头尾节点的话,需互相绑定,但双链表比单链表找节点更灵活,甚至可以头尾一起找节点
在此基础上堆栈的实现,请点击这里跳跃