Java链表
- 一、单向链表的基本介绍
- 二、单向链表基础功能的实现
- 1.创建头结点
- 初始化头结点
- 2.向链表中插入数据
- 3.计算链表的长度
- 3.删除重复节点
- 4.删除指定值的节点
- 5.打印链表
- 6.链表反转
- 7.查找单链表的中间节点
- 8.查找倒数第k个元素
- 9.对链表进行排序
- 链表功能引用
一、单向链表的基本介绍
数组和链表都是最基础的线性数据结构,可以用来实现栈,队列等非线性,有特定应用场景的数据结构,我们发现数组作为数据存储结构有很很多缺陷,在无序数组中搜索效率低,在有序数组中插入效率又很低,无论哪种情况删除操作效率都很低;而且数组一旦创建,大小不可更改。
- 相邻元素之间通过指针链接
- 最后一个元素的后继指针为NULL
- 在程序执行过程中,链表的长度可以增加或缩小
- 链表的空间能够按需分配
- 没有内存空间的浪费
如下图所示,在数据结构中,a1里面的指针存储着a2的地址,这样一个链接一个,就形成了链表。
下图描述了单向链表存储情况。存储是分散的,每一个节点只要记录下一节点,就把所有数据串了起来,形成了一个单向链表。
节点(Node)是由一个需要储存的对象及对下一个节点的引用组成的。也就是说,节点拥有两个成员:储存的对象、对下一个节点的引用。下面图是具体的说明:
链表的优点: - 插入和删除时不需移动其他元素, 只需改变指针,效率高。
- 链表各个节点在内存中空间不要求连续,空间利用率高。
- 大小没有固定,拓展很灵活。
链表的缺点 - 查找数据时效率低,因为不具有随机访问性。
二、单向链表基础功能的实现
1.创建头结点
class Node {
Node next = null;// 节点的引用,指向下一个节点
int date;//链表中的节点,data代表节点的值,next是指向下一个节点的引用
public Node(int n){
this.date=n;
}
}
初始化头结点
Node head = null;
2.向链表中插入数据
public void addNode(int d) {
Node newNode = new Node(d); //实例化一个节点
if (head == null) {
head = newNode;
return;
}
Node tmp = head;
while (tmp.next != null) {
tmp = tmp.next;
}
tmp.next = newNode;
}
3.计算链表的长度
public int length() {
int len = 0;
Node tmp = head;
while (tmp != null) {
len++;
tmp = tmp.next;
}
return len;
}
3.删除重复节点
public void deleteDuplecate() {
Node p = head;
while (p != null) {
Node q = p;
while (q.next != null) {
if (p.date == q.next.date) {
q.next = q.next.next;
} else
q = q.next;
}
p = p.next;
}
}
4.删除指定值的节点
public void delete(int n) {
while (head.date==n&&head.next!=null)//处理链表头部值连续相同的情况
{
head=head.next;
}
if(head.date==n)
return null;
Node p=head;
while (p.next != null) {
if (p.next.date == n) {
p.next = p.next.next;
} else
p = p.next;
}
}
5.打印链表
public void printlist() {
Node L = head;
while (L != null) {
System.out.println(L.date);
L = L.next;
}
}
6.链表反转
public void reversaL(){
Node ReversaHead =head;
Node pNode=head;
Node pRive=null;
while (pNode!=null)
{
Node pNext=pNode.next;
if(pNext==null)
{
ReversaHead=pNode;
}
pNode.next=pRive;
pRive=pNode;
pNode=pNext;
}
this.head=ReversaHead;
//return this.head;
}
7.查找单链表的中间节点
public Node SearchMid(Node head) {
Node p = this.head, q = this.head;
while (p != null && p.next != null && p.next.next != null) {
p = p.next.next;
q = q.next;
}
System.out.println("Mid:" + q.data);
return q;
}
8.查找倒数第k个元素
采用两个指针P1,P2,P1先前移K步,然后P1、P2同时移动,当p1移动到尾部时,P2所指位置的元素即倒数第k个元素 。
public Node findElem(Node head, int k) {
if (k < 1 || k > this.length()) {
return null;
}
Node p1 = head;
Node p2 = head;
for (int i = 0; i < k; i++)// 前移k步
p1 = p1.next;
while (p1 != null) {
p1 = p1.next;
p2 = p2.next;
}
return p2;
}
9.对链表进行排序
public Node orderList() {
Node nextNode = null;
int tmp = 0;
Node curNode = head;
while (curNode.next != null) {
nextNode = curNode.next;
while (nextNode != null) {
if (curNode.data > nextNode.data) {
tmp = curNode.data;
curNode.data = nextNode.data;
nextNode.data = tmp;
}
nextNode = nextNode.next;
}
curNode = curNode.next;
}
return head;
}
链表功能引用
在主函数中引用
public class LinkedList {
public static void main(String[] args) {
Listdemo list=new Listdemo();
LinkedList<Integer>
Scanner sc=new Scanner(System.in);
int sum=sc.nextInt();
for (int i=0;i<sum;i++)
{
int s=sc.nextInt();
list.addNode(s);
}
System.out.println("length="+list.length());
//list.printlist();
//list.deleteDuplecate();
//list.delete(15);
//System.out.println("length="+list.length());
//list.delete(5);
//list.printlist();
list.reversaL();
list.printlist();
}
}