01 概念
存储空间是不连续的,由存储地址链接起来。 单链表,由头指针确定,可以用头指针的名字来命名。
每个节点由两部分组成:1.数据元素。2.指向下一个节点的指针。
还有双链表(由两个指针域,指向前后元素)和循环链表(首尾相接)
单链表中的几个概念:
1.头指针:指向链表中第一个节点的指针(相当于是链表名) 2.首元节点:链表中存储第一个数据元素的节点 3.头节点:在链表首元节点之前附设的一个节点
所以,单链表有两种类型:带头结点和不带头节点
如何表示空表呢? 无头节点时 head=null; 有头节点时 head.next = null
设置头节点的好处: 1.便于首元节点的处理 2.便于空表和非空表的处理
头节点数据域中装的是什么呢?可以自己定义,注意 头节点不计入链表长度
链表的特点:
1.逻辑上相邻的元素在物理位置上不一定相邻 2.访问时,只能通过头指针进入链表,需要以此向后顺序遍历其它节点
02单链表的定义
链表类:
class SingleLinkList {
LinkListNode head; //定义单链表的头节点
int length; //定义单链表的长度
}
节点类:
class LinkListNode {
Integer data; //数据域
LinkListNode next;//指针域
}
03单链表基本操作的实现
单链表的初始化
//初始化单链表
public SingleLinkList() {
this.head = new LinkListNode();
}
判断链表是否为空
//判断链表是否为空
public boolean isEmpty(){
return length==0;
}
单链表的销毁
//销毁单链表,链表销毁后不存在
public void destroyList(){
head = null;
}
单链表的清空
//清空单链表,链表仍存在,只剩头节点
public void clearList(){
head.next=null;
}
获取单链表表长
//获取单链表的表长
public int getLength(){
return length;
}
获取第i个元素值
//取第i个元素的值
public Integer getElem(int i){
//先判断i是否合法
if (i>=1 && i<=getLength()){
LinkListNode p = head;
while (i>0){
p = p.next;
i--;
}
return p.data;
}
throw new RuntimeException("输入不合法");
}
按值查找获取元素第一次出现的位置
//按值查找,获取指定元素第一次出现的位置
public int getLocal(Integer target){
LinkListNode p = head.next;
while (p != null){
if (p.data == target){
return p.data;
}else {
p = p.next;
}
}
throw new RuntimeException("元素不存在");
}
在第i个节点前插入新的节点
//在第i个节点前插入新的节点
public void insertElem(int i ,Integer ele){
LinkListNode temp ;
LinkListNode p = head;
if (i>=1 && i<=getLength()){
//先找到第i-1个节点
while (--i>0){
p = p.next;
}
}else {
throw new RuntimeException("输入不合法");
}
temp = p.next;
//创建新节点,并插入
p.next = new LinkListNode(ele,temp);
length++;
}
删除第i个节点
//删除第i个节点
public void deleteElem(int i ){
LinkListNode temp ;
LinkListNode p = head;
if (i>=1 && i<=getLength()){
//先找到第i-1个节点
while (--i>0){
p = p.next;
}
}else {
throw new RuntimeException("输入不合法");
}
//删除节点
p.next = p.next.next;
length--;
}
头插法和尾插法建立链表
/**
* 单链表的建立 头插法
* @param ele 插入的链表,以数组的形式作为输入
*/
public void createList_H(Integer[] ele){
LinkListNode temp = head;
for (int i = ele.length-1; i >= 0 ; i--) {
head.next = new LinkListNode(ele[i],temp);
temp = head.next;
length++;
}
}
/**
* 单链表的建立 尾插法
* @param ele 插入的链表,以数组的形式作为输入
*/
public void createList_R(Integer[] ele){
LinkListNode last = head;//尾指针指向头节点
for (int i = 0; i < ele.length ; i++) {
last.next = new LinkListNode(ele[i],null);
last = last.next;
length++;
}
}
//遍历链表并输出
public void traverseList(){
LinkListNode p = head.next;
for (int i = 0; i < getLength(); i++) {
System.out.print(p.data+"\t");
p = p.next;
}
}
测试
package linkedlist;
import java.sql.Array;
public class SingleLinkListTest {
public static void main(String[] args) {
SingleLinkList list = new SingleLinkList();
Integer[] arr = {1,2,3,4,5,6,7,8,9};
list.createList_R(arr);
System.out.println(list.getLength());
System.out.println(list.getElem(3));
System.out.println(list.getLocal(3));
list.insertElem(3,0);
list.deleteElem(10);
list.traverseList();
}
}