赞
踩
为了提高大家的学习效率,我把代码放开头,供查阅。
目录
- //无头单向链表
- package demo1;
- public class MySingleLinkedList{
- class ListNode{
- public int var;
- public ListNode next;
- public int val;
-
- public ListNode(int var) {
- this.var = var;
- }
- }
- ListNode head;
- public void creat(){
- ListNode node1=new ListNode(1);
- ListNode node2=new ListNode(1);
- ListNode node3=new ListNode(1);
- ListNode node4=new ListNode(1);
-
- node1.next=node2;
- node2.next=node3;
- node3.next=node4;
- head=node1;
- }
- //头插法
- public void addFirst(int data) {
- ListNode node=new ListNode(data);
- node.next=head;
- head=node;
- }
- //尾插法
- public void addLast(int data) {
- ListNode node=new ListNode(data);
- if(head==null){
- head=node;
- return;
- }
- ListNode cur=head;
- while (cur.next!=null){
- cur=cur.next;
- }cur.next=node;
- }
-
- private void IndexCheck(int index)throws IndexNotLegal {
- if(index<0||index>size()){
- throw new IndexNotLegal("index位置不合法");
- }
- }
- //任意位置插入,第一个数据节点为0号下标
- public void addIndex(int index, int data){
- try {
- IndexCheck(index);
- }catch (IndexNotLegal e){
- e.printStackTrace();
- return;
- }
- ListNode node=new ListNode(data);
- ListNode cur=head;
- if(index==0){
- addFirst(data);
- return;
- }if(index==size()){
- addLast(data);
- return;
- }
- //注意这里是index-1
- for (int i = 0; i < index-1; i++) {
- cur= cur.next;
- }
- node.next=cur.next;
- cur.next=node;
- }
- //查找是否包含关键字key是否在单链表当中
- public boolean contains(int key) {
- ListNode cur=head;
- while (cur!=null){
- if(cur.var==key){
- return true;
- }cur=cur.next;
- }return false;
- }
- //删除第一次出现关键字为key的节点
- public void remove(int key) {
- if(head.var==key){
- head=head.next;
- return;
- }if(head==null){
- return;
- }
- ListNode cur=head;
- while (cur.next!=null){
- if(cur.next.var==key){
- cur.next=cur.next.next;
- return;
- }cur=cur.next;
- }
- }
- //删除所有出现的key节点
- public void removeAllKey(int key) {
- if(head==null){
- return;
- }ListNode prev=head;
- ListNode cur=head.next;
- while (cur!=null){
- if(cur.var==key){
- prev.next= cur.next;
- //这里不能写prev=cur
- cur= cur.next;
- }else {
- prev=cur;
- cur= cur.next;
- }
- if(head.var==key){
- head=head.next;
- }
- }
-
- }
- //得到单链表的长度
- public int size() {
- ListNode cur=head;
- int count=0;
- while (cur!=null){
- count++;
- cur=cur.next;
- }return count;
- }
- //打印链表
- public void display() {
- ListNode cur=head;
- for (int i = 0; i < size(); i++) {
- System.out.print(cur.var+" ");
- cur=cur.next;
- }
- System.out.println();
- }
- //清除链表
- public void clear() {
- head=null;
- }
- }
-
- public class IndexNotLegal extends RuntimeException {
- public IndexNotLegal(){
-
- }public IndexNotLegal(String s){
- super(s);
- }
- }
-
-
-
-
-
-
-
-
-
-
-
- package demo2;
- // 无头双向链表
- public class MyLinkedList {
-
- class ListNode {
- public int var;
- ListNode prev;
- ListNode next;
-
- public ListNode(int var) {
- this.var = var;
- }
- }
-
- ListNode head;
- ListNode last;
-
- //头插法
- public void addFirst(int data) {
- ListNode node = new ListNode(data);
- if (head == null) {
- head = last = node;
- return;
- }
- node.next = head;
- head.prev = node;
- head = node;
- }
-
- //尾插法
- public void addLast(int data) {
- ListNode node = new ListNode(data);
- if (head == null) {
- head = last = node;
- return;
- }
- last.next = node;
- node.prev = last;
- last = node;
- }
-
- private void indexCheck(int index) throws IndexNotLegal {
- if (index < 0 || index > size()) {
- throw new IndexNotLegal("index位置不合法");
- }
- }
-
- private ListNode findIndexCur(int index) {
- ListNode cur = head;
- while (index != 0) {
- cur = cur.next;
- index--;
- }
- return cur;
- }
-
- //任意位置插入,第一个数据节点为0号下标
- public void addIndex(int index, int data) {
- try {
- indexCheck(index);
- } catch (IndexNotLegal e) {
- e.printStackTrace();
- }
-
- if (index == 0) {
- addFirst(data);
- return;
- }
- if (index == size()) {
- addLast(data);
- return;
- }
- ListNode node = new ListNode(data);
- ListNode cur = findIndexCur(index);
- //先把node插进去,再调整node的前一个,最后再调cur,因为需要cur来调整
- node.next=cur;
- cur.prev.next=node;
- node.prev=cur.prev;
- cur.prev=node;
-
-
- }
-
- //查找是否包含关键字key是否在单链表当中
- public boolean contains(int key) {
- ListNode cur = head;
- while (cur != null) {
- if (cur.var == key) {
- return true;
- }
- cur = cur.next;
- }
- return false;
- }
-
- //删除第一次出现关键字为key的节点
- public void remove(int key) {
- ListNode cur = head;
- while (cur != null) {
- if (cur.var == key) {
- //头节点
- if (head.var == key) {
- head.next.prev = null;
- head = head.next;
- return;
- }
- //尾巴节点
- if (last.var == key) {
- last.prev.next = null;
- last = last.prev;
- return;
- }
- cur.next.prev = cur.prev;
- cur.prev.next = cur.next;
- return;
- }
- cur = cur.next;
- }
- }
-
- //删除所有值为key的节点
- public void removeAllKey(int key) {
- ListNode cur = head;
- while (cur != null) {
- if (cur.var == key) {
- //头节点
- if (head.var == key) {
- head.next.prev = null;
- head = head.next;
- return;
- }
- //尾巴节点
- if (last.var == key) {
- last.prev.next = null;
- last = last.prev;
- return;
- }
- cur.next.prev = cur.prev;
- cur.prev.next = cur.next;
- }
- cur = cur.next;
- }
- }
-
-
-
- //得到单链表的长度
- public int size() {
- int count = 0;
- ListNode cur = head;
- while (cur != null) {
- cur = cur.next;
- count++;
- }
- return count;
- }
-
- public void display() {
- ListNode cur = head;
- for (int i = 0; i < size(); i++) {
- System.out.print(cur.var + " ");
- cur = cur.next;
- }
- System.out.println();
- }
-
- public void clear() {
- head = last = null;
- }
- }
-
-
- package demo2;
-
- public class IndexNotLegal extends RuntimeException{
- public IndexNotLegal(){
-
- }public IndexNotLegal(String s){
- super(s);
- }
- }
简单来说,像链子一样的数据结构。像火车一节一节车厢一样,每个元素是独立的个体(内部类)。 并且他们在空间里是分散的。
为什么分散的还可以找到下一个呢?
答:一个节点里面装着两种东西,一个是值,一个的下一个的地址,这样根据下一个的地址就可以找到下一个了。
常见的链表有三种,但是我这里只介绍两种:无头单链,无头双链。剩下的一种之后再补充。
单链和双链的区别?
答: 一个节点都是一个类。单链装的是值和下个节点;双链装的是值和上个节点和下个节点
怎么插入元素?在链表中很简单!
单链:p下个节点改成n1,n0下个节点改为p。
双链: p下个节点改为n1,n0下个节点改为p(先把p插进去,成一个逆时针),p上个节点改为n0,n1的上个节点改为p(修改原来的两点节点)
注意!还需要考虑一些特殊情况,具体请看代码的实现!
在链表中删除节点也非常方便,只需改变一个节点的引用(指针)即可。
单链:n0的下个节点指向n1。
双链:n0下个节点改为n1,n1上个节点改为n0 。
问题来了:为什么p的指向n1可以不删?
答;原因是以及没人指向p了, 如果没人引用(指向)的东西,就会被系统自动回收。 像clear()方法,head不指向首个节点,那么首个节点被回收,同理下面也如此。
方法 | 解释 |
LinkedList() | 无参构造 |
public LinkedList(Collection c) | 使用其他集合容器中元素构造List |
- public static void main(String[] args) {
- // 构造一个空的LinkedList
- List<Integer> list1 = new LinkedList<>();
- List<String> list2 = new java.util.ArrayList<>();
- list2.add("JavaSE");
- list2.add("JavaWeb");
- list2.add("JavaEE");
- // 使用ArrayList构造LinkedList
- List<String> list3 = new LinkedList<>(list2);
- }
方法 | 解释 |
boolean add(E e) | 尾插 e |
void add(int index, E element) | 将 e 插入到 index 位置 |
boolean addAll(Collection c) | 尾插 c 中的元素 |
E remove(int index) | 删除 index 位置元素 |
boolean remove(Object o) | 删除遇到的第一个 o |
E get(int index) | 获取下标 index 位置元素 |
E set(int index, E element) | 将下标 index 位置元素设置为 element |
void clear() | 清空 |
boolean contains(Object o) | 判断 o 是否在线性表中 |
int indexOf(Object o) | 返回第一个 o 所在下标 |
int lastIndexOf(Object o) | 返回最后一个 o 的下标 |
List subList(int fromIndex, int toIndex) | 截取部分 list |
- public static void main(String[] args) {
- LinkedList<Integer> list = new LinkedList<>();
- list.add(1); // add(elem): 表示尾插
- list.add(2);
- list.add(3);
- list.add(4);
- list.add(5);
- list.add(6);
- list.add(7);
- System.out.println(list.size());
- System.out.println(list);
- // 在起始位置插入0
- list.add(0, 0); // add(index, elem): 在index位置插入元素elem
- System.out.println(list);
- list.remove(); // remove(): 删除第一个元素,内部调用的是removeFirst()
- list.removeFirst(); // removeFirst(): 删除第一个元素
- list.removeLast(); // removeLast(): 删除最后元素
- list.remove(1); // remove(index): 删除index位置的元素
- System.out.println(list);
- // contains(elem): 检测elem元素是否存在,如果存在返回true,否则返回false
- if(!list.contains(1)){
- list.add(0, 1);
- }
- list.add(1);
- System.out.println(list);
- System.out.println(list.indexOf(1)); // indexOf(elem): 从前往后找到第一个elem的位置
- System.out.println(list.lastIndexOf(1)); // lastIndexOf(elem): 从后往前找第一个1的位置
- int elem = list.get(0); // get(index): 获取指定位置元素
- list.set(0, 100); // set(index, elem): 将index位置的元素设置为elem
- System.out.println(list);
- // subList(from, to): 用list中[from, to)之间的元素构造一个新的LinkedList返回
- List<Integer> copy = list.subList(0, 3);
- System.out.println(list);
- System.out.println(copy);
- list.clear(); // 将list中元素清空
- System.out.println(list.size());
- }
- public static void main(String[] args) {
- LinkedList<Integer> list = new LinkedList<>();
- list.add(1); // add(elem): 表示尾插
- list.add(2);
- list.add(3);
- list.add(4);
- list.add(5);
- list.add(6);
- list.add(7);
- System.out.println(list.size());
- //for循环遍历
- for (int i = 0; i < list.size(); i++) {
- System.out.print(list.get(i)+" ");
- }
- // foreach遍历
- for (int e:list) {
- System.out.print(e + " ");
- }
- System.out.println();
- // 使用迭代器遍历---正向遍历
- ListIterator<Integer> it = list.listIterator();
- while(it.hasNext()){
- System.out.print(it.next()+ " ");
- }
- System.out.println();
- // 使用反向迭代器---反向遍历
- ListIterator<Integer> rit = list.listIterator(list.size());
- while (rit.hasPrevious()){
- System.out.print(rit.previous() +" ");
- }
- System.out.println();
- }
不同点 | 数组 | 链表 |
存储方式 | 连续内存空间 | 分散内存空间 |
容量扩展 | 长度不可变 | 可灵活扩展 |
内存效率 | 元素占用内存少、但可能浪费空间 | 元素占用内存多 |
访问元素 | O(1) | O(N) |
添加元素 | O(N) | O(1) |
删除元素 | O(N) | O(1) |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。