Java数据结构——不带头单向非循环链表
一、链表的概念
链表:采用链式存储结构存储的线性表,所谓的链式是指每个节点保存下一个节点的引用
链表的分类:
- 单向、双向
- 带头节点、不带头节点
- 循环、非循环
根据以上三种分类,即可组成八种不同类型的链表
链表的特点:
链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理,但是链表失去了顺序表可以随机读取的优点,同时,链表增加了节点的指针域,空间开销比较大。
二、不带头单向非循环链表
1.结构图
2. 节点类组成
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;
}
}
3. 常用的链表操作
1)遍历链表
2)头插法
3)尾插法
4) 任意位置插入
5) 删除第一次出现关键字为key的节点
6) 删除所有关键字为key的节点
7)清空链表
4. 接口
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();
}
5. 实现类
public class MySingleList implements ILinked{
//内部节点类
class Node {
private int data;//存储该节点中的元素
public Node next;//引用下一个节点
//节点类构造方法
public Node(int data) {
this.data = data;
this.next = null;
}
}
private Node head;//头节点
//链表类构造方法
public MySingleList() {
this.head = null;
}
@Override
//头插法
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 {
//1、找尾巴
while(cur.next != null) {
cur = cur.next;
}
//退出上面的循环,cur所指向的位置就是尾节点
cur.next = node;
}
}
// 返回index位置的节点
private Node searchIndex(int index){
checkIndex(index);
int count=0;
Node cur=this.head;
while(count<index-1){
cur=cur.next;
count++;
}
return cur;
}
//检验index位置合法性
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
//查找是否包含关键字key是否在单链表当中
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
//删除第一次出现关键字为key的节点
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;
}
//删除所有关键字为key的节点
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;
}