单链表
最近在恶补数据结构和算法,我看的书是《java数据结构与算法 第二版》,我也会在博客上记录我的学习过程。
《java数据结构与算法 第二版》书中把冗长的代码中重要的代码独立出来讲解,我觉得这种方式很好,阅读简单,思路清晰,能看清各个模块之间的关系。今天我会用这种庖丁解牛的方式一步步实现单链表数据结构。
Link类
1 public class Link { 2 public int data1;//数据1 3 public String data2;//数据2 4 public Link next;//指向下一个链结点 5 //构造函数 初始化 6 public Link(int d1,String d2){ 7 this.data1=d1; 8 this.data2=d2; 9 //next 会被自动赋值为null,意味着这个字段不指向任何结点 10 } 11 public void displayLink(){ 12 System.out.println("数据1:"+data1+","+"数据2:"+data2); 13 } 14 }
LinkList类
定义了对链表中对第一个节点的引用,叫做first。从first出发,沿着链表中每个链结点的next字段,就可以找到其他链结点
1 class LinkList{ 2 3 private Link first; 4 //构造函数 5 public LinkList(){ 6 first=null;//虽然first成员变量会被自动赋值为null,但是为了让我们的代码更加易读,在这里强调下first是怎么开始运作的 7 } 8 //用来判断first是否为空 9 public boolean isEmpty(){ 10 return (first==null); 11 } 12 13 }
insertFirst()
作用是在表头插入一个新的结点。只需要使新创建的结点的next指向原来first的值,然后改变first的值,让它指向新的结点。如图所示
1 public void insertFirst(int d1,String d2){ 2 //创建一个新结点 3 Link newLink=new Link(d1,d2); 4 newLink.next=first; 5 first=newLink; 6 }
find(key)
查找结点,一个叫current的变量开始时指向first,然后不断赋值为current.next,沿着链表移动,直到它找到与传进来的key相等的值,返回该结点的引用。如果没有找到对应的值,则返回null
1 public Link find(int key){ 2 Link current=first;//指向第一个结点 3 while (current.data1!=key){ 4 if(current.next==null){ 5 return null;//到达链表尾部返回null 6 }else{ 7 current=current.next;//没找到移到下一个结点 8 } 9 } 10 return current; 11 }
deleteFirst()
删除表头,如图
1 public Link deleteFirst(){ 2 Link temp =first; 3 first=first.next; 4 return temp; 5 }
delete(key)
删除方法和find()方法类似。先找到要删除的结点,同时获得指向前一个结点的引用和指向后一个结点的引用(即要删除结点的next),然后修改前一个结点的引用,使它指向后一个结点。
1 public Link delete(int key){ 2 Link current=first; 3 Link previous=first; 4 while(current.data1!=key){ 5 if(current.next==null){ 6 return null;//到达链表尾部没有找到数据 7 }else{ 8 previous=current;//前一个继续向下移动 9 current=current.next;//当前向下移动 10 } 11 } 12 //如果找到了跳出循环 13 if(current==first){ 14 first=first.next;//如果找到的是第一个,则删掉表头,指向下一个结点 15 }else{ 16 previous.next=current.next; 17 } 18 return current;//返回被删除的结点 Ps:被删除的结点其实还在内存中的某个地方,但是已经没有任何引用指向它了,在java中,GC会在某个时刻销毁它,不用我们操心 19 }
displayList()
为了显示链表,从first开始,沿着引用链从一个结点到下一个结点
1 public void displayList(){ 2 System.out.println("开始打印链表"); 3 Link current=first; 4 while(current!=null){ 5 current.displayLink(); 6 current=current.next; 7 } 8 System.out.println("结束"); 9 }
下面给出完整的代码
1 public class Link { 2 public int data1;//数据1 3 public String data2;//数据2 4 public Link next;//指向下一个链结点 5 //构造函数 初始化 6 public Link(int d1,String d2){ 7 this.data1=d1; 8 this.data2=d2; 9 //next 会被自动赋值为null 10 } 11 public void displayLink(){ 12 System.out.println("数据1:"+data1+","+"数据2:"+data2); 13 } 14 } 15 class LinkList{ 16 17 private Link first; 18 //构造函数 19 public LinkList(){ 20 first=null;//虽然first成员变量会被自动赋值为null,但是为了让我们的代码更加易读,在这里强调下first是怎么开始运作的 21 } 22 //用来判断first是否为空 23 public boolean isEmpty(){ 24 return (first==null); 25 } 26 public void insertFirst(int d1,String d2){ 27 //创建一个新结点 28 Link newLink=new Link(d1,d2); 29 newLink.next=first; 30 first=newLink; 31 } 32 public Link find(int key){ 33 Link current=first;//指向第一个结点 34 while (current.data1!=key){ 35 if(current.next==null){ 36 return null;//到达链表尾部返回null 37 }else{ 38 current=current.next;//没找到移到下一个结点 39 } 40 } 41 return current; 42 } 43 public Link delete(int key){ 44 Link current=first; 45 Link previous=first; 46 while(current.data1!=key){ 47 if(current.next==null){ 48 return null;//到达链表尾部没有找到数据 49 }else{ 50 previous=current;//前一个继续向下移动 51 current=current.next;//当前向下移动 52 } 53 } 54 //如果找到了跳出循环 55 if(current==first){ 56 first=first.next;//如果找到的是第一个,则删掉表头,指向下一个结点 57 }else{ 58 previous.next=current.next; 59 } 60 return current;//返回被删除的结点 61 } 62 public Link deleteFirst(){ 63 Link temp =first; 64 first=first.next; 65 return temp; 66 } 67 public void displayList(){ 68 System.out.println("开始打印链表"); 69 Link current=first; 70 while(current!=null){ 71 current.displayLink(); 72 current=current.next; 73 } 74 System.out.println("结束"); 75 } 76 77 }
Test类
1 public class Test { 2 public static void main(String[] args) { 3 LinkList linkList=new LinkList(); 4 linkList.insertFirst(1, "老王"); 5 linkList.insertFirst(2, "小明"); 6 linkList.insertFirst(3, "萌妹");//插入3个数据 7 linkList.displayList(); 8 linkList.deleteFirst();//删除表头 9 linkList.displayList(); 10 linkList.find(1).displayLink();//查找key为1的数据 11 linkList.displayList(); 12 linkList.delete(1).displayLink();//删除key为1的数据 13 linkList.displayList(); 14 } 15 }
开始打印链表 数据1:3,数据2:萌妹 数据1:2,数据2:小明 数据1:1,数据2:老王 结束 开始打印链表 数据1:2,数据2:小明 数据1:1,数据2:老王 结束 数据1:1,数据2:老王 开始打印链表 数据1:2,数据2:小明 数据1:1,数据2:老王 结束 数据1:1,数据2:老王 开始打印链表 数据1:2,数据2:小明 结束