单链表(Java)
单链表是链表的一种基本结构
在结点中数据域用来存储数据元素,指针域用于指向下一个具有相同结构的结点。
链表由头指针唯一确定,单链表可以用头指针的名字来命名
一个最简单的结点结构如图所示,它是构成单链表的基本结点结构
单链表的基本操作
单链表的基本操作有:
-
增(add):
2. 头插法
//头插法:如果链表没有头结点,新结点直接成为新结点;否则新结点的next直接指向当前头结点,并让新结点成为头结点
public static void addheadNode(int data){
Node newNode = new Node(data);
if (head == null) { //头结点不存在,新结点成为头结点
head = newNode;
return;
}
newNode.next = head;//新结点指向当前头结点
head = newNode; //新结点成为头结点
}
2. 尾插法
//尾插法:如果链表没有头结点,新结点直接成为头结点;否则先找到链表的当前尾结点,把新结点插入到链表的尾部
public static void addtailNode(int data) {
Node newNode = new Node(data);
if(head==null) {
head=newNode;
return;
}
Node last=head;
while(last.next!=null) {//找到最后一个结点
last=last.next;
}
last.next=newNode;//新结点插入到链表尾部
}
3. 在指定位置插入
//在指定位置插入结点:先判断插入位置为头尾两端的情况,即插入到头部:index == 0,插入到尾部:index == size();
//如果插入位置不是头尾两端,则先找出当前index位置的结点以及前一个结点
public static void addNodeAtindex(int data,int index) {
if (index < 0 || index > length()) { //注意index是可以等于size()的
throw new IndexOutOfBoundsException("IndexOutOfBoundsException");
}
if (index == 0) { //插入到头部
addheadNode(data);
} else if (index == length()) { //插入到尾部
addtailNode(data);
} else { //插到某个中间位置
Node newNode = new Node(data);
int position = 0;
Node cur = head; //标记当前结点
Node pre = null; //记录前置结点
while (cur != null) {
if (position == index) {
newNode.next = cur;
pre.next = newNode;
return;
}
pre = cur;
cur = cur.next;
position++;
}
}
}
-
删(delete)
1.删除结点
public static void removeNode(int data) {
Node pre=null;
Node cur=head;
while(cur!=null) {
if(cur.data==data) {
if(cur==head) {
head=cur.next;
}
else {
pre.next=cur.next;
}
break;
}
else {
pre=cur;
cur=cur.next;
}
}
}
-
查(search)
- 求倒数第K个结点
public static int getLast(int k) {
if (k < 0 || k > length()) { //注意index是可以等于size()的
throw new IndexOutOfBoundsException("IndexOutOfBoundsException");
}
Node cur = head;
for (int i = 1; i < length() - k + 1; i++) {
cur = cur.next;
}
return cur.data;
}
2.查找结点是否存在
public static boolean searchNode(int data) {
Node cur=head;
while(cur!=null) {
if(cur.data==data) {
return true;
}
else {
cur=cur.next;
}
}
return false;
}
-
改(change)
1. 链表逆序(反转)
public static void reverseNode() {
Node cur=head;
Node pre=null;
Node temp;
while(cur!=null) {
temp=cur.next;//保存当前结点的下一结点
cur.next=pre;//指针顺序置换
pre=cur;//指针继续后移
cur=temp;
}
head=pre;//最后一个结点变为新的头结点
}
......
完整代码如下:
public class LinkList {
public static class Node{//创建单链表
int data;//数据域
Node next;//指针域
public Node(int data) {//构造
this.data=data;
this.next=null;
}
}
private static Node head;
public static boolean isempty(Node head) {//判断链表是否为
return head == null ? true : false;
}
public static int length() { // 链表长度
if (isempty(head)) {
return 0;
}
int length = 1;
Node cur = head;
while (cur.next != null) {
length++;
cur = cur.next;
}
return length;
}
//头插法:如果链表没有头结点,新结点直接成为新结点;否则新结点的next直接指向当前头结点,并让新结点成为头结点
public static void addheadNode(int data){
Node newNode = new Node(data);
if (head == null) { //头结点不存在,新结点成为头结点
head = newNode;
return;
}
newNode.next = head;//新结点指向当前头结点
head = newNode; //新结点成为头结点
}
//尾插法:如果链表没有头结点,新结点直接成为头结点;否则先找到链表的当前尾结点,把新结点插入到链表的尾部
public static void addtailNode(int data) {
Node newNode = new Node(data);
if(head==null) {
head=newNode;
return;
}
Node last=head;
while(last.next!=null) {//找到最后一个结点
last=last.next;
}
last.next=newNode;//新结点插入到链表尾部
}
//在指定位置插入结点:先判断插入位置为头尾两端的情况,即插入到头部:index == 0,插入到尾部:index == size();
//如果插入位置不是头尾两端,则先找出当前index位置的结点以及前一个结点
public static void addNodeAtindex(int data,int index) {
if (index < 0 || index > length()) { //注意index是可以等于size()的
throw new IndexOutOfBoundsException("IndexOutOfBoundsException");
}
if (index == 0) { //插入到头部
addheadNode(data);
} else if (index == length()) { //插入到尾部
addtailNode(data);
} else { //插到某个中间位置
Node newNode = new Node(data);
int position = 0;
Node cur = head; //标记当前结点
Node pre = null; //记录前置结点
while (cur != null) {
if (position == index) {
newNode.next = cur;
pre.next = newNode;
return;
}
pre = cur;
cur = cur.next;
position++;
}
}
}
//删除结点
public static void removeNode(int data) {
Node pre=null;
Node cur=head;
while(cur!=null) {
if(cur.data==data) {
if(cur==head) {
head=cur.next;
}
else {
pre.next=cur.next;
}
break;
}
else {
pre=cur;
cur=cur.next;
}
}
}
//删除指定结点元素
public static void delindexNode(int index) {
if (index < 0 || index > length() - 1) {
throw new IndexOutOfBoundsException("IndexOutOfBoundsException");
}
if (index == 0) { //删除头
head = head.next;
return;
}
int position = 0; //记录当前位置
Node cur = head; //标记当前结点
Node pre = null; //记录前置结点
while (cur != null) {
if (position == index) {
pre.next = cur.next;
cur.next = null; //断开cur与链表的连接
return;
}
pre = cur;
cur = cur.next;
position++;
}
}
//查找节点是否存在
public static boolean searchNode(int data) {
Node cur=head;
while(cur!=null) {
if(cur.data==data) {
return true;
}
else {
cur=cur.next;
}
}
return false;
}
//链表反转
public static void reverseNode() {
Node cur=head;
Node pre=null;
Node temp;
while(cur!=null) {
temp=cur.next;//保存当前结点的下一结点
cur.next=pre;//指针顺序置换
pre=cur;//指针继续后移
cur=temp;
}
head=pre;//最后一个结点变为新的头结点
}
//求倒数第K个结点
public static int getLast(int k) {
if (k < 0 || k > length()) { //注意index是可以等于size()的
throw new IndexOutOfBoundsException("IndexOutOfBoundsException");
}
Node cur = head;
for (int i = 1; i < length() - k + 1; i++) {
cur = cur.next;
}
return cur.data;
}
//遍历链表
public static void show() {
Node cur=head;
while(cur!=null) {
System.out.print(cur.data+" ");
cur=cur.next;
}
System.out.println("");
}
public static void main(String[] args) {
System.out.println("头插法:");
addheadNode(1);
addheadNode(2);
addheadNode(3);
addheadNode(4);
show();
System.out.println("尾插法:");
addtailNode(5);
addtailNode(6);
addtailNode(7);
addtailNode(8);
show();
System.out.println("删除“4”和“6”:");
removeNode(4);
removeNode(6);
show();
System.out.println("在指定位置插入:");
addNodeAtindex(9,3);
show();
System.out.println("链表反转:");
reverseNode();
show();
System.out.println("求倒数第K个结点:");
System.out.println(getLast(3));
}
}