链表的组合形式
①有头结点、无头结点
②单向链表、双向链表
③循环链表、非循环链表
根据自由组合,可以得到8种不同形式的链表,那么在刷题种常碰到的是不带有头结点的单向非循环链表和不带头结点的双向非循环链表。
模拟实现不带头结点的单向非循环链表的操作
public class MySingleLinkedList {
//无头单向非循环链表的实现
static class ListNode {
int val; //数值域
ListNode next; //指向下一结点
public ListNode(int val) {
this.val = val;
}
}
public ListNode head; //记录链表的头
public void createNode() {
ListNode listNode1 = new ListNode(1);
ListNode listNode2 = new ListNode(3);
ListNode listNode3 = new ListNode(5);
ListNode listNode4 = new ListNode(7);
listNode1.next = listNode2;
listNode2.next = listNode3;
listNode3.next = listNode4;
head = listNode1;
}
//头插法
public void addFirst(int data){
ListNode node = new ListNode(data); //实例化这个结点
if (head == null) {
head = node;
}
//链表不为空的时候
node.next = head;
head = node;
}
//尾插法
public void addLast(int data){
ListNode node = new ListNode(data); //实例化这个结点
if (head == null) {
head = node;
}
//找到尾结点
ListNode cur = head;
while (cur.next != null) {
cur = cur.next;
}//此时cur指向的就是尾结点
cur.next = node;
}
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
if (index < 0 || index > size()) {
//抛异常
throw new IndexOutException("插入下标不合法");
}
if (index == 0) {
//头插
addFirst(data);
}
if (index == size()) {
//尾插
addLast(data);
}
//中间插
ListNode cur = head;
while (index-1 > 0) {
cur = cur.next;
index--;
}//此时cur是要插入的前一个结点
ListNode node = new ListNode(data); //实例化这个结点
node.next = cur.next;
cur.next = node;
}
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
if (head == null) {
return false;
}
ListNode cur = head;
while (cur != null) {
if (cur.val == key) {
return true;
}
cur = cur.next;
}
return false;
}
//删除第一次出现关键字为key的节点
public void remove(int key){
if (head == null) {
System.out.println("删除失败");
return;
}
if (head.val == key) {
head = head.next;
return;
}
ListNode cur = head;
while (cur.next != null) {
if (cur.next.val == key) {
cur.next = cur.next.next;
return;
}else {
cur = cur.next;
}
}
}
//删除所有值为key的节点
public void removeAllKey(int key){
if (head == null) {
System.out.println("删除失败");
return;
}
while (head.val == key) {
head = head.next;
}
ListNode curPre = head;
ListNode cur = head.next;
while (cur != null) {
if (cur.val == key) {
curPre.next = cur.next;
cur = cur.next;
}else {
curPre = curPre.next;
cur = cur.next;
}
}
}
//得到单链表的长度
public int size(){
if (head == null) {
return -1;
}
ListNode cur = head; //为了让头结点不发生改变
int count = 0;
while (cur != null) {
count++;
cur = cur.next;
}
return count;
}
public void clear() {
ListNode cur = head;
while (cur != null) {
ListNode curNext = cur.next;
cur.next = null;
cur = curNext;
}
head = null;
}
public void display() {
ListNode cur = head; //为了让头结点不发生改变
while (cur != null) {
System.out.print(cur.val + " ");
cur = cur.next;
}
System.out.println();
}
}
public class MyLinkedList {
//模拟双向链表
static class ListNode {
int val; //数值域
ListNode next; //指向下一结点
ListNode prev; //指向上一结点
public ListNode(int val) {
this.val = val;
}
}
public ListNode head; //头结点
public ListNode last; //尾结点
//创建结点
public void createNode() {
ListNode listNode1 = new ListNode(1);
ListNode listNode2 = new ListNode(3);
ListNode listNode3 = new ListNode(5);
ListNode listNode4 = new ListNode(7);
listNode1.next = listNode2;
listNode2.prev = listNode1;
listNode2.next = listNode3;
listNode3.prev = listNode2;
listNode3.next = listNode4;
listNode4.prev = listNode3;
head = listNode1;
last = listNode4;
}
//头插法
public void addFirst(int data){
ListNode node = new ListNode(data);
if (head == null) {
head = node;
last = node;
}else{
node.next = head;
head = node;
}
}
//尾插法
public void addLast(int data){
ListNode node = new ListNode(data);
if (last == null ) {
head = node;
last = node;
}else {
last.next = node;
last = node;
}
}
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
if (index < 0 || index > size()) {
throw new IndexOutException("下标不合法");
}
if (index == 0) {
addFirst(data);
return;
}
if (index == size()) {
addLast(data);
return;
}
ListNode cur = head;
ListNode node = new ListNode(data);
//找到要插入结点的前一个结点
while (index-1 > 0) {
cur = cur.next;
index--;
}
node.next = cur.next;
cur.next = node;
node.next.prev = node;
node.prev = cur;
}
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
ListNode cur = head;
while (cur != null) {
if (cur.val == key) {
return true;
}
cur = cur.next;
}
return false;
}
//删除第一次出现关键字为key的节点
public void remove(int key){
if (head == null) {
return;
}
if (head.val == key) {
if (head == last) {
head = null;
last = null;
return;
}else {
head = head.next;
head.prev = null;
return;
}
}
if (last.val == key) {
if (head == last) {
head = null;
last = null;
return;
}else {
last = last.prev;
last.next = null;
return;
}
}
//要删的在中间
ListNode cur = head;
ListNode curNext = head.next;
while (curNext != null) {
if (curNext.val == key) {
cur.next = curNext.next;
curNext.next.prev = cur;
return;
}else {
cur = cur.next;
curNext = curNext.next;
}
}
}
//删除所有值为key的节点
public void removeAllKey(int key){
ListNode cur = head;
while (cur != null) {
if(cur.val == key) {
//判断当前是不是头节点
if(cur == head) {
head = head.next;
if(head != null) {
head.prev = null;//一个节点
}
}else {
//中间和尾巴的情况
cur.prev.next = cur.next;
if(cur.next != null) {
cur.next.prev = cur.prev;
}else {
last = last.prev;
}
}
cur = cur.next;
}else {
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;
while (cur != null) {
System.out.print(cur.val +" ");
cur = cur.next;
}
System.out.println();
}
public void clear(){
ListNode cur = head;
while (cur != null) {
ListNode curNext = cur.next;
cur.next = null;
cur.prev = null;
cur = curNext;
}
head = null;
last = null;
}
}
List<Integer> list = new ArrayList<>();
list.add(1);
LinkedList<Integer> list1 = new LinkedList<>();
list1.add(6);
LinkedList<Integer> list2 = new LinkedList<>(list);
System.out.println(list1);
System.out.println(list2);
①第一种是无参构造
②第二种是带参数构造,传入一个其他集合容器种的元素
LinkedList<Integer> list = new LinkedList<>();
list.add(1);
list.add(2);
list.add(3);
①sout直接输出(必然重写例如toString)
System.out.println(list);
②for-each
for (int x: list) {
System.out.println(x);
}
③迭代器
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext()) {
System.out.print(iterator.next());
}
//逆序
ListIterator<Integer> iterator1 = list.listIterator(list.size());
while (iterator1.hasPrevious()) {
System.out.print(iterator1.previous());
}