70人参与 • 2024-08-06 • 数据结构
链表就是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。
也是线性表。
数据域:存储数据元素信息的域。
指针域:存储直接后继的信息。
链表根据三个条件分类:
根据以上3个条件来分类(每一个条件选一),链表一共有8种。
单链表全称为:无头单向不循环链表。
自己实现一个单链表(存储int数据类型),将单链表作为一个类,我们实现一些“接口”即成员方法来实现数据的增删查改。
// 1、无头单向非循环链表实现
public class singlelinkedlist {
//头插法
public void addfirst(int data);
//尾插法
public void addlast(int data);
//任意位置插入,第一个数据节点为0号下标
public boolean 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 clear();
}
因为我们需要使用数据域,指针域,在链表中一个一个串起来。那我们就将数据域指针域使用一个静态内部类来封装。只将第一个节点用head来表示。
注意:此处的head不是链表分类时的头,因为分类的头的数据域的数据是无效的而此处是有效的。
public class singlelinkedlist {
static class listnode{
public int val;
public listnode next;
public listnode(int val) {
this.val = val;
}
}
public listnode head;
}
实现思路:
将当前节点的下一个节点(next)指向头(head),再改头为当前节点。
public void addfirst(int data) {
listnode cur = new listnode(data);
cur.next = head;
head = cur;
}
实现思路:
public void addlast(int data){
if(head == null){
head = new listnode(data);
return;
}
listnode cur = head;
while(cur.next != null){
cur = cur.next;
}
cur.next = new listnode(data);
}
实现思路:
public boolean addindex(int index,int data) throws indexillegalexception{
try{
if(index < 0 || index > size()){
throw new indexillegalexception("位置不合法");
} else if (index == 0) {
addfirst(data);
return true;
} else if (index == size()) {
addlast(data);
return true;
}else{
listnode cur = head;
listnode pre = head;
listnode newnode = new listnode(data);
for (int i = 0; i < index-1; i++) {
cur = cur.next;
pre = pre.next;
}
newnode.next = cur.next;
pre.next = cur;
return true;
}
}catch(indexillegalexception e){
e.printstacktrace();
return false;
}
}
使用循环遍历即可。
public boolean contains(int key){
listnode cur = head;
for (int i = 0; i < size(); i++) {
if(cur.val == key){
return true;
}
cur = cur.next;
}
return false;
}
实现思路:
public void remove(int key){
if(head == null){
return;
} else if (head .val == key) {
head = head.next;
return;
}
listnode cur = head.next;
listnode pre = head;
while(cur != null){
if(cur.val == key){
pre.next = cur.next;
return;
}
cur = cur.next;
pre = pre.next;
}
}
跟删除一个节点一个逻辑只不过删除后不返回,并且头结点最后判断。
public void removeallkey(int key){
if(head == null){
return;
}
listnode cur = head.next;
listnode pre = head;
while(cur != null){
if(cur.val == key){
pre.next = cur.next;
cur = cur.next;
}else {
cur = cur.next;
pre = pre.next;
}
}
if(head.val == key){
head = head.next;
}
}
直接循环遍历就行。
public int size(){
listnode cur = head;
int size = 0;
while(cur != null){
cur = cur.next;
size++;
}
return size;
}
直接循环将每一个节点置空,注意置空前要将头先向后走。
public void clear(){
listnode cur = head;
while (cur != null){
head = cur.next;
cur = null;
cur = head;
}
}
优缺点如下:
在java的集合类中使用的是无头双向非循环链表。
自己实现一个双向链表(存储int数据类型),将双向链表作为一个类,我们实现一些“接口”即成员方法来实现数据的增删查改。
// 2、无头双向链表实现
public class linkedlist {
//头插法
public void addfirst(int data);
//尾插法
public void addlast(int data);
//任意位置插入,第一个数据节点为0号下标
public boolean 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 clear();
}
因为我们需要使用数据域,指针域,在链表中一个一个串起来。那我们就将数据域指针域使用一个静态内部类来封装。只将第一个节点用head来表示,最后一个节点用last表示。
注意:此处的head不是链表分类时的头,因为分类的头的数据域的数据是无效的而此处是有效的。
static class listnode{
public int val;
public listnode prev;
public listnode next;
public listnode(int val) {
this.val = val;
}
}
public listnode head;
public listnode last;
实现思路:
public void addfirst(int data){
listnode cur = new listnode(data);
if(head == null){
head = last = cur;
return;
}
cur.next = head;
head.prev = cur;
head = cur;
}
实现思路:
public void addlast(int data){
listnode cur = new listnode(data);
if(last == null){
head = last = cur;
return;
}
last.next = cur;
cur.prev = last;
last = cur;
}
实现思路:
public boolean addindex(int index,int data) throws indexillegalexception{
try{
if(index < 0 || index > size()){
throw new indexillegalexception("插入位置不合法");
} else if (index == 0) {
addfirst(data);
return true;
} else if (index == size()) {
addlast(data);
return true;
}else {
listnode cur = head;
listnode newnode = new listnode(data);
for (int i = 0; i < index; i++) {
cur = cur.next;
}
newnode.prev = cur.prev;
cur.prev = newnode;
newnode.next = cur;
return true;
}
}catch (indexillegalexception e){
e.printstacktrace();
return false;
}
}
直接循环遍历就行。
public boolean contains(int key){
listnode cur = head;
while(cur != null){
if(cur.val == key){
return true;
}
cur = cur.next;
}
return false;
}
实现思路:
public void remove(int key){
listnode cur = head;
if(head.val == key){
head.next.prev = null;
head = head.next;
return;
} else {
while(cur.next != null){
if(cur.val == key){
cur.prev.next = cur.next;
cur.next.prev = cur.prev;
return;
}
cur = cur.next;
}
if (last.val == key) {
last.prev.next = null;
last = last.prev;
return;
}
}
}
public void removeallkey(int key){
listnode cur = head.next;
while(cur.next != null){
if(cur.val == key){
cur.prev.next = cur.next;
cur.next.prev = cur.prev;
}
cur = cur.next;
}
if(head.val == key){
head.next.prev = null;
head = head.next;
}
if (last.val == key) {
last.prev.next = null;
last = last.prev;
}
}
直接循环遍历即可。
public int size(){
listnode cur = head;
int size = 0;
while(cur != null){
size++;
cur = cur.next;
}
return size;
}
实现思路:
public void clear(){
listnode cur = head;
while(cur != null){
listnode curnext = cur.next;
cur.prev = null;
cur.next = null;
cur = curnext;
}
head = null;
last = null;
}
}
在java中用集合类linkedlist来表示双向链表。
接口说明:
java中提供了两个构造方法。
方法 | 方法用途介绍 |
---|---|
linkedlist() | 无参构造 |
public linkedlist(collection<? extends e> c) | 使用其他集合容器中元素构造list |
提供的常用方法与上面实现的差不多。
优缺点如下:
对比如下图:
删除链表中等于给定值 val 的所有节点
反转一个单链表
链表的中间节点
合并两个有序链表
链表分割
链表的回文结构
相交链表
环形链表
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论