数据结构-------单链表
单链表:
在计算机科学中,链表是数据元素的线性组合,元素储存上并不连续。
可以分为:单向链表、双向链表、循环链表
单向链表:
首先,定义结点的类型,它包括值和下一个结点。
头部插入法:
相关java代码:
1 private Node head;//定义头部结点 2 public class Node{ 3 private int value;//每个结点的值 4 private Node next;//指向下一个结点 5 public Node(int value,Node next) { 6 this.value=value; 7 this.next=next; 8 } 9 } 10 //实现添加元素的方法 11 public void addFirwst(int value) { 12 // head = new Node(value,null) ;//假设链表为空,也就是head为空 这一行代码和下一行代码功能一样 head为空那么new Node(value,head) 13 head = new Node(value,head);//假设链表不为空 赋值完成之后作为头部节点 14 } 15 //while循环遍历元素loop 16 public void loop1() { 17 Node p = head; 18 while(p!=null) { 19 System.out.print(p.value+"\t"); 20 p=p.next; 21 } 22 }
相关测试代码:
1 SingleLinkList singlelinklist = new SingleLinkList(); 2 singlelinklist.addFirwst(6); 3 singlelinklist.addFirwst(2); 4 singlelinklist.addFirwst(8); 5 singlelinklist.addFirwst(12); 6 singlelinklist.addFirwst(0); 7 System.out.println("遍历元素loop1:"); 8 singlelinklist.loop1();
结果显示:每次添加元素 添加的顺序为 6 12 8 2 6存放到链表中,由此可见,每次添加元素向头添加元素(头插法),并将新的结点作为头节点。
各种遍历方法:
除了上述代码中的while循环还有for循环和迭代器和Consumer等方法,方法改变了条件不变作为遍历的条件。
//for循环遍历元素 public void loop2() { for(Node p=head;p!=null;p=p.next) { System.out.print(p.value+"\t"); } } //通过Consumer来遍历元素 public void loop3(Consumer<Integer> consumer) { for(Node p=head;p!=null;p=p.next) { consumer.accept(p.value); } } //通过迭代器来遍历元素 @Override public Iterator<Integer> iterator() { // TODO Auto-generated method stub return new Iterator<Integer>() { Node p =head; @Override public boolean hasNext() { // TODO Auto-generated method stub return p!=null; } @Override public Integer next() { // TODO Auto-generated method stub int value = p.value; p=p.next; return value; } }; }
尾部插入法:
尾部插入法,首先要找到最后一个元素,只有找到最后一个元素,才能够往后面添加元素。
1 //尾插法 尾部插入 主要找到尾部最后一个元素 2 private Node findLast() { 3 if(head==null) { 4 return null; 5 } 6 Node p; 7 for(p=head;p.next!=null;p=p.next) { 8 9 } 10 return p; 11 } 12 public void addLast(int value) { 13 Node last = findLast();//找到最后一个元素 14 if(last==null) { 15 addFirwst(value); 16 return; 17 } 18 last.next = new Node(value,null); 19 }
相关测试代码:
1 singlelinklist.addLast(22); 2 singlelinklist.addLast(18); 3 singlelinklist.addLast(6); 4 singlelinklist.addLast(8); 5 singlelinklist.addLast(2); 6 for(Integer value:singlelinklist) {//迭代方式遍历 7 System.out.print(value+"\t"); 8 }
效果如下,由此可见尾插法遍历和插入的顺序一致,头部插入顺序和遍历顺序相反。
根据索引值求返回值:
根据索引来找到元素:参数[传入索引] 记录每次元素的索引值,但不保存下来,保存下来会消耗大量的空间。
1 //根据索引求返回值 2 private Node findNode(int index) { 3 int i=0; 4 Node p; 5 for(p=head;p!=null;p=p.next,i++) { 6 if(i==index) { 7 return p; 8 } 9 } 10 return null; 11 } 12 public int get(int index) { 13 Node p = findNode(index); 14 if(p==null) { 15 throw new IllegalArgumentException(String.format("index [%d] 不合法", index)); 16 } 17 return p.value; 18 }
相关结果测试
1 //测试获取某个值 2 int a = singlelinklist.get(0); 3 int b = singlelinklist.get(1); 4 int c = singlelinklist.get(2); 5 int d = singlelinklist.get(3); 6 int e = singlelinklist.get(4); 7 8 9 System.out.println(); 10 System.out.println("获取下标元素值:a="+a+"\t\tb="+b+"\tc="+c+"\td="+d+"\te="+e); 11 int f = singlelinklist.get(5); 12 System.out.println("f="+f);
结果显示:
根据索引值添加元素:
添加元素,你要知道上一个元素和下一个元素。
1 //给出索引添加元素 2 public void insert(int index,int value) { 3 if(index==0) { 4 addFirwst(value); 5 return; 6 } 7 Node prev = findNode(index-1);//找到当前元素的前一个元素 8 if(prev==null) { 9 throw new IllegalArgumentException(String.format("index [%d] 不合法", index)); 10 } 11 prev.next = new Node(value,prev.next);//new Node(value,prev.next) 中的prev.next为下一个元素的值 12 13 }
相关测试代码:
//按照索引添加元素 System.out.println("\n添加元素:"); singlelinklist.insert(1, 20); for(Integer value:singlelinklist) { System.out.print(value+"\t"); }
结果显示,根据索引添加元素值。
删除第一个元素:
1 //删除第一个元素 2 public void removeFirst() { 3 if(head==null) { 4 throw new IllegalArgumentException(String.format("index [%d] 不合法")); 5 } 6 head = head.next; 7 }
相关测试代码:
1 System.out.println("\n删除元素:"); 2 singlelinklist.removeFirst(); 3 for(Integer value:singlelinklist) { 4 System.out.print(value+"\t"); 5 }
结果显示:
根据索引删除元素:
1 //根据索引删除元素 2 public void remove(int index) { 3 //根据index-1前面一个元素 4 if(index==0) { 5 removeFirst(); 6 } 7 Node prev = findNode(index-1); 8 if(prev==null) { 9 throw new IllegalArgumentException(String.format("index [%d] 不合法")); 10 } 11 Node removed = prev.next; 12 if(removed==null) { 13 throw new IllegalArgumentException(String.format("index [%d] 不合法")); 14 } 15 prev.next = removed.next; 16 17 }
根据索引,删除值,这个时候需要考虑的东西比较多,如果你要删除第一个元素和上面removeFirst()方法一样,如果这个列表只有一个元素也需要考虑。