链表
1.概念
链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。
实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:
- 单向、双向
- 带头、不带头
- 循环、非循环
虽然有这么多的链表的结构,但是我们实际中最常用还是三种结构:
- 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。
- 带头循环单链表:结构较无头单向非循环链表简单。实际操作当中使用较少。
- 不带头双向链表:在Java的集合框架库中LinkedList底层实现就是不带头双向循环链表。
1、无头单向非循环链表实现
// 1、无头单向非循环链表实现
public interface ILinked {
//头插法
void addFirst(int data);
//尾插法
void addLast(int data);
//任意位置插入,第一个数据节点为0号下标
boolean addindex(int index,int data);
//查找是否包含关键字key是否在单链表当中
boolean contains(int key);
//删除第一次出现关键字为key的节点
int remove(int key);
//删除所有值为key的节点
void removeAllKey(int key);
//得到单链表的长度
int getLength();
void display();
void clear();
}
实现:
public class MySingleListImpl implements ILinked {
class Node {
private int data;
private Node next;
public Node(int data) {
this.data = data;
this.next = null;
}
public int getData() {
return data;
}
}//节点类
private Node head;
public MySingleListImpl() {
this.head = null;
}
@Override
public void addFirst(int data) {
Node node = new Node(data);
if (this.head != null) {
node.next = this.head;
this.head = node;
} else {
this.head = node;
}
}
/* public void addFirst(int data) {
Node node = new Node(data);
if(this.head == null) {
this.head = node;
}else {
node.next = this.head;
this.head = node;
}
}
*/
@Override
public void addLast(int data) {
Node node = new Node(data);
Node cur = this.head;
//如果是第一次插入的时候
if (cur == null) {
this.head = node;
} else {
while (cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
}
/*public void addLast(int data) {
Node node = new Node(data);
Node cur = this.head;
//如果是第一次插入
if(cur == null) {
this.head = node;
}else {
//1、找尾巴
while(cur.next != null) {
cur = cur.next;
}
//退出上面的循环,cur所指向的位置就是尾节点
cur.next = node;
}
}*/
/**
* 找到index-1的位置的节点
*
* @param index
* @return
*/
private Node searchIndex(int index) {
checkIndex(index);
/*int count = index-1;
Node cur = this.head;
while(count != 0) {
cur = cur.next;
count--;
}*/
int count = 0;
Node cur = this.head;
while (count < index - 1) {
cur = cur.next;
count++;
}
return cur;
}
private void checkIndex(int index) {
if (index < 0 || index > getLength()) {
throw new UnsupportedOperationException("index位置不合法");
}
}
@Override
public boolean addIndex(int index, int data) {
//头部插入
if (index == 0) {
addFirst(data);
return true;
}
Node node = new Node(data);
Node cur = searchIndex(index);
node.next = cur.next;
cur.next = node;
return true;
}
@Override
public boolean contains(int key) {
Node cur = this.head;
while (cur != null) {
if (cur.data == key) {
return true;
}
cur = cur.next;
}
return false;
}
private Node searchPrev(int key) {
Node cur = this.head;
while (cur.next != null) {
if (cur.next.data == key) {
return cur;
}
cur = cur.next;
}
return null;
}
@Override
public int remove(int key) {
if (this.head == null) {
throw new UnsupportedOperationException("单链表为空");
}
int oldData = 0;
//删除的节点是头结点
if (this.head.data == key) {
oldData = this.head.data;
this.head = this.head.next;
return oldData;
}
Node prev = searchPrev(key);
if (prev == null) {
//return
throw new UnsupportedOperationException("没有前驱");
}
Node del = prev.next;
oldData = del.data;
prev.next = del.next;
//del = null;
return oldData;
}
@Override
public void removeAllKey(int key) {
if (this.head == null) {
return;
}
Node prev = this.head;
Node cur = this.head.next;
while (cur != null) {
if (cur.data == key) {
prev.next = cur.next;
cur = prev.next;
} else {
prev = cur;
cur = cur.next;
}
}
if (this.head.data == key) {
this.head = this.head.next;
}
}
@Override
public int getLength() {
if (this.head == null) {
return 0;
}
int count = 0;
Node cur = this.head;
while (cur != null) {
count++;
cur = cur.next;
}
return count;
}
@Override
public void display() {
Node cur = this.head;
while (cur != null) {
System.out.print(cur.data + " ");
cur = cur.next;
}
System.out.println();
}
@Override
public void clear() {
while (this.head.next != null) {
Node del = this.head.next;
this.head.next = del.next;
}
this.head = null;
}
2、带头循环单链表实现
//2、带头循环单链表实现
public interface ICLinked {
//头插法
void addFirst(int data);
//尾插法
void addLast(int data);
//任意位置插入,第一个数据节点为0号下标
boolean addindex(int index,int data);
//查找是否包含关键字key是否在单链表当中
boolean contains(int key);
//删除第一次出现关键字为key的节点
int remove(int key);
//删除所有值为key的节点
void removeAllKey(int key);
//得到单链表的长度
int getLength();
void display();
void clear();
}
实现:
public class MyHeadSingleListImpl implements ICLinked{
class Node {
private int data;
private Node next;
public Node(int data) {
this.data = data;
this.next = null;
}
//头结点
public Node() {
this.data = -1;
this.next = null;
}
}
private Node head;
public MyHeadSingleListImpl() {
this.head = new Node();
this.head.next = this.head;
}
@Override
public void addFirst(int data) {
Node node = new Node(data);
node.next = this.head.next;
this.head.next = node;
}
@Override
public void addLast(int data) {
Node cur = this.head;
while(cur.next != this.head) {
cur = cur.next;
}
Node node = new Node(data);
node.next = cur.next;
cur.next = node;
}
private void checkIndex(int index) {
if(index < 0 || index > getLength()){
throw new UnsupportedOperationException("index位置不合法");
}
}
@Override
public boolean addIndex(int index, int data) {
checkIndex(index);
Node cur = this.head;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
//cur就是index位置的前驱
Node node = new Node(data);
node.next = cur.next;
cur.next = node;
return true;
}
@Override
public boolean contains(int key) {
Node cur = this.head.next;
while(cur != this.head) {
if(cur.data == key) {
return true;
}
cur = cur.next;
}
return false;
}
private Node searchPrev(int key){
Node cur = this.head;
while (cur.next != this.head) {
if(cur.next.data == key){
return cur;
}
cur = cur.next;
}
return null;
}
@Override
public int remove(int key) {
Node prev=searchPrev(key);
if(prev == null) {
return -1;
}
int oldData = 0;
Node del = prev.next;
oldData = del.data;
prev.next = del.next;
return oldData;
}
@Override
public void removeAllKey(int key) {
if(this.head == null || this.head.next == this.head) {
return;
}
Node prev = this.head;
Node cur = this.head.next;
while (cur != this.head) {
if(cur.data == key){
prev.next = cur.next;
cur = prev.next;
}else {
prev = cur;
cur = cur.next;
}
}
}
@Override
public int getLength() {
int count = 0;
Node cur = this.head.next;
while(cur != this.head) {
count++;
cur = cur.next;
}
return count;
}
@Override
public void display() {
Node cur = this.head.next;
while (cur != this.head) {
System.out.print(cur.data+" ");
cur = cur.next;
}
System.out.println();
}
@Override
public void clear() {
while(this.head.next != this.head) {
Node cur = this.head.next;
this.head.next = cur.next;
}
this.head = null;
}
}
3.不带头双向链表实现
//不带头双向链表实现
public interface IDoubleLinked {
//头插法
void addFirst(int data);
//尾插法
void addLast(int data);
//任意位置插入,第一个数据节点为0号下标
boolean addindex(int index,int data);
//查找是否包含关键字key是否在单链表当中
boolean contains(int key);
//删除第一次出现关键字为key的节点
int remove(int key);
//删除所有值为key的节点
void removeAllKey(int key);
//得到单链表的长度
int getLength();
void display();
void clear();
}
实现:
public class MyDoubleLinkList implements IDoubleLinked {
class Node {
private int data;
private Node prev;
private Node next;
public Node(int data) {
this.data = data;
this.next = null;
}
}
private Node head;
private Node last;
public MyDoubleLinkList(){
this.head =null;
this.last =null;
}
@Override
public void addFirst(int data) {
Node node = new Node(data);
if(this.head == null){
this.head = node;
this.last = node;
}else{
node.next = this.head;
this.head.prev = node;
this.head = node;
}
}
@Override
public void addLast(int data) {
Node node = new Node(data);
if(this.head == null){
this.head = node;
this.last = node;
}else {
this.last.next = node;
node.prev = this.last;
this.last = node;
}
}
private Node searchIndex(int index) {
checkIndex(index);
int count = 0;
Node cur = this.head;
while(count != index) {
cur = cur.next;
count++;//1 2
}
return cur;
}
private void checkIndex(int index) {
if(index < 0 || index > getLength()){
throw new UnsupportedOperationException("index位置不合法");
}
}
@Override
public boolean addIndex(int index, int data) {
if(index == 0) {
addFirst(data);
return true;
}
if(index == getLength()){
addLast(data);
return true;
}
Node cur = searchIndex(index);
//cur 指向index位置的节点
Node node = new Node(data);
node.next = cur;
cur.prev.next = node;
node.prev = cur.prev;
cur.prev=node;
return true;
}
@Override
public boolean contains(int key) {
Node cur =this.head;
while (cur != null){
if(cur.data == key){
return true;
}
cur = cur.next;
}
return false;
}
@Override
public int remove(int key) {
Node cur= this.head;
int oldData = 0;
while (cur != null){
if(cur.data == key) {
oldData = cur.data;
if (cur == this.head) { //删除头结点
this.head = this.head.next;
this.head.prev = null;
} else {
cur.prev.next = cur.next;
//cur.next != null不是尾节点
if (cur.next != null) {
cur.next.prev = cur.prev;
} else {
// cur.prev.next = cur.next;
this.last = cur.prev;
}
}
return oldData;
}
cur = cur.next;
}
return -1;
}
@Override
public void removeAllKey(int key) {
Node cur= this.head;
while (cur != null){
if(cur.data == key) {
if (cur == this.head) { //删除头结点
this.head = this.head.next;
this.head.prev = null;
} else {
cur.prev.next = cur.next;
//cur.next != null不是尾节点
if (cur.next != null) {
cur.next.prev = cur.prev;
} else {
// cur.prev.next = cur.next;
this.last = cur.prev;
}
}
}
cur = cur.next;
}
}
@Override
public int getLength() {
int count =0;
Node cur =this.head;
while (cur!=null){
count++;
cur=cur.next;
}
return count;
}
@Override
public void display() {
Node cur = this.head;
while(cur != null) {
System.out.print(cur.data+" ");
cur = cur.next;
}
System.out.println();
}
@Override
public void clear() {
//Node cur =this.head;
//while (cur != null){
while (this.head != null){
Node cur =this.head.next;
this.head.next = null;
this.head.prev = null;
this.head = cur;
}
}
}