文章目录
前言
今天我学习了一种新的数据结构–链表,我将分享给大家两种链表的具体实现。
一、无头单向非循环链表
最简单的链表,一般不会单独用来储存数据,实际中作为其他数据结构的子结构,
如:图的邻接表。
1.无头单向循环链表的实现
1.1List接口
用来存放即将实现的方法
public interface IList {
public void addFirst(int data);
//尾插法
public void addLast(int data);
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data) throws IndexException;
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key);
//删除第一次出现关键字为key的节点
public void remove(int key);
//删除所有值为key的节点
public void removeAllKey(int key);
//得到单链表的长度
public int size();
public void clear();
public void display() ;
}
1.2MySingLlistl类
里面将具体实现List接口中的方法
1.链表的基本属性
static class ListNode{
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
}
而head节点应该定义在ListNode的外部
public ListNode head;
2.具体方法的实现
public class MySingleList implements IList {
static class ListNode{
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
}
public ListNode head;
@Override
//插入数据的时候先绑后面的,防止数据丢失
public void addFirst(int data) {
ListNode node=new ListNode(data);
node.next=head;
head=node;
}
@Override
public void addLast(int data) {
ListNode node=new ListNode(data);
if(head==null){
head=node;
}else{
ListNode cur=head;
while(cur.next!=null){
cur=cur.next;
}
cur.next=node;
}
}
@Override
public void addIndex (int index, int data) throws IndexException {
ListNode node =new ListNode(data);
if(index<0||index>size()){
throw new IndexException("index位置不合法:"+index);
}
if(head==null){
head=node;
}
if(index==0){
addFirst(data);
return;
}
if(index==size()){
addLast(data);
return;
}
ListNode cur=findPrevIndex(index);
node.next=cur.next;
cur.next=node;
}
public ListNode findPrevIndex(int index){
ListNode cur=head;
int count=0;
while (count<index-1){
count++;
cur=cur.next;
}
return cur;
}
@Override
public boolean contains(int key) {
ListNode cur=head;
while (cur!=null){
if(cur.val==key){
return true;
}
cur=cur.next;
}
return false;
}
@Override
public void remove(int key) {
if(head.val==key){
head=head.next;
}
if(head==null){
return;
}
ListNode cur=findPreKey(key);
if(cur==null){
return;//没有要删除的key值
}
ListNode del=cur.next;
cur.next=del.next;
}
private ListNode findPreKey(int key){
ListNode cur=head;
while (cur.next!=null){
if(cur.next.val==key){
return cur;
}else{
cur=cur.next;
}
}
return null;
} public int size() {
ListNode cur=head;
int count=0;
while (cur!=null){
count++;
cur=cur.next;
}
return count;
}
@Override
public void clear() {
head=null;
}
@Override
public void display() {
ListNode cur=head;
while (cur!=null){
System.out.print(cur.val+" ");
cur=cur.next;
}
System.out.println();
}
1.3IndexException类
用来处理任意位置插入时index的位置的不合法问题
public class IndexException extends RuntimeException{
public IndexException(String message) {
super(message);
}
public IndexException() {
}
}
1.4Main类
用来测试的类
public class Main {
public static void main(String[] args) {
MySingleList mySingleList=new MySingleList();
//mySingleList.creatList();
mySingleList.display();
System.out.println(mySingleList.contains(23));
System.out.println(mySingleList.size());
mySingleList.addFirst(12);
mySingleList.addFirst(23);
mySingleList.addLast(34);
mySingleList.addFirst(45);
mySingleList.display();
System.out.println(mySingleList.size());
mySingleList.addIndex(4,66);
mySingleList.display();
mySingleList.clear();
}
}
1.5运行截图
二、无头双向非循环链表
在javad的底层集合框架中LinkedList的底层逻辑就是无头双向非循环链表
2.无头双向非循环链表的实现
2.1List接口
用来存放即将实现的方法
package List;
public interface List {
public void addFirst(int data);
//尾插法
public void addLast(int data);
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data);
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key);
//删除第一次出现关键字为key的节点
public void remove(int key);
//删除所有值为key的节点
public void removeAllKey(int key);
//得到单链表的长度
public int size();
public void display();
public void clear();
}
2.2MyLinkedList类
无头双向链表的具体实现
1.无头双向链表的属性
比单向链表多了一个前驱节点prev,且记录了最后一个节点的地址last
static class ListNode{
int val;
ListNode prev;
ListNode next;
public ListNode(int val) {
this.val=val;
}
}
ListNode head;
ListNode last;
2.具体实现
package List;
public class MyLinkedList implements List{
static class ListNode{
int val;
ListNode prev;
ListNode next;
public ListNode(int val) {
this.val=val;
}
}
ListNode head;
ListNode last;
@Override
public void addFirst(int data) {
ListNode node=new ListNode(data);
if(head==null){
head=node;
last=node;
}else {
node.next=head;
head.prev=node;
head=node;
}
}
@Override
public void addLast(int data) {
ListNode node=new ListNode(data);
if(head==null){
head=node;
last=node;
}else{
last.next=node;
node.prev=last;
last=node;
}
}
@Override
public void addIndex(int index, int data) {
ListNode node=new ListNode(data);
checkIndex(index);
if(index==0){
addFirst(data);
return;
}
if(index==size()){
addLast(data);
return;
}
ListNode cur=findIndex(index);
node.next=cur;
cur.prev.next=node;
node.prev=cur.prev;
cur.prev=node;
}
public void checkIndex(int index){
if(index<0||index>size()){
throw new IndexException("index位置不合法;"+index);
}
}
public ListNode findIndex(int index){
ListNode cur=head;
while(index!=0){
cur=cur.next;
index--;
}
return cur;
}
@Override
public boolean contains(int key) {
ListNode cur=head;
while(cur!=null){
if(cur.val==key){
return true;
}
cur=cur.next;
}
return false;
}
@Override
public void remove(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 {
last = null;
}
} else {
//删除中间节点
if (cur.next != null) {
cur.next.prev=cur.prev;
cur.prev.next=cur.next;
}else{
//删除尾巴节点
cur.prev.next=cur.next;
last=last.prev;
}
}
return;
}
cur=cur.next;
}
}
@Override
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 {
last = null;
}
} else {
//删除中间节点
if (cur.next != null) {
cur.prev.next=cur.next;
cur.next.prev=cur.prev;
}else{
//删除尾巴节点
cur.prev.next=null;
last=last.prev;
}
}
}
cur=cur.next;
}
}
@Override
public int size() {
int count=0;
ListNode cur=head;
while(cur!=null){
count++;
cur=cur.next;
}
return count;
}
@Override
public void display() {
ListNode cur=head;
while(cur!=null){
System.out.println(cur.val+" ");
cur=cur.next;
}
System.out.println();
}
@Override
public void clear() {
head=null;
last=null;
}
}
2.3IndexException类
用来记录插入位置index异常的类
package List;
public class IndexException extends RuntimeException{
public IndexException() {
}
public IndexException(String message) {
super(message);
}
}
2.4Test类
用来测试方法
package List;
public class Test {
public static void main(String[] args) {
MyLinkedList myLinkedList=new MyLinkedList();
myLinkedList.addFirst(12);
myLinkedList.addFirst(23);
myLinkedList.addFirst(34);
myLinkedList.addFirst(45);
myLinkedList.display();
myLinkedList.addLast(56);
myLinkedList.display();
myLinkedList.addIndex(3,72);
myLinkedList.display();
myLinkedList.remove(72);
myLinkedList.display();
}
}
2.5运行截图
总结
以上就是今天要讲的内容,如果大家想多了解无头单向循环链表的面试题,可以去看我的另一个专栏—数据结构的应用,感谢大家的浏览!!!