数据结构 线性结构篇——链表,linux应用开发面试

本文详细介绍了Java链表的插入(set)、查找(contains)、删除(remove)和获取(get)操作的时间复杂度,并展示了如何实现链表栈和队列,涵盖了链表的基本操作、复杂度讨论和实际应用场景。
摘要由CSDN通过智能技术生成

}

//在链表的index(0-based)位置添加新的元素e

public void set(int index,E e){

if(index < 0 || index > size)

throw new IllegalArgumentException(“Set failed. Illegal index.”);

Node cur = dummyHead.next;

for (int i = 0; i < index; i++)

cur = cur.next;

cur.e = e;

}

//查找链表中是否有元素e

public boolean contains(E e){

Node cur = dummyHead.next;

while (cur != null){

if(cur.e.equals(e))

return true;

cur = cur.next;

}

return false;

}

4.5.1 修改和查找操作时间复杂度

| 功能 | 时间复杂度 |

| — | — |

| set(index,e) | O(n) |

| get(index) | O(n) |

| contains(e) | O(n) |

4.5 删除链表元素

加入我们想要删除索引为 (2) 位置的元素,我们需要找到 待删除节点之前的一个位置,也就是(1) ,我们用 prev 表示,找到这个节点之后,那么 (2) 就是我们需要删除的索引了 我们叫 delNode,如下图所示:

在这里插入图片描述

代码实现:

//从链表中删除Index(0-based)位置的元素,返回删除的元素

public E remove(int index){

if(index < 0 || index > size)

throw new IllegalArgumentException(“Remove failed. Illegal index.”);

Node prev = dummyHead;

for (int i = 0; i < index; i++)

prev = prev.next;

Node retNode = prev.next;

prev.next = retNode.next;

retNode.next = null;

size --;

return retNode.e;

}

//从链表中删除第一个位置的元素

public E removeFirst(){

return remove(0);

}

//从链表中删除最后一个位置的元素

public E removeLast(){

return remove(size - 1);

}

4.5.1 删除操作时间复杂度

| 功能 | 时间复杂度 |

| — | — |

| removeList(e) | O(n) |

| removeFirst(e) | O(1) |

| remove(index,e) | O(n/2) = O(n) |

4.6 完整代码

/**

  • 底层链表的内部类

  • @param

*/

public class LinkedList {

private class Node{

public E e;

public Node next;//public 可以在LinkedList随意操作

public Node(E e,Node next){

this.e = e;

this.next = next;

}

public Node(E e){

this(e,null);

}

public Node(){

this(null,null);

}

@Override

public String toString() {

return e.toString();

}

}

private Node dummyHead;

int size;

public LinkedList(){

dummyHead = new Node(null,null);

size = 0;

}

//获取链表中的元素个数

public int getSize(){

return size;

}

//返回链表是否为空

public boolean isEmpty(){

return size == 0;

}

//在链表头中添加元素e

public void addFirst(E e){

//方式一

// Node node = new Node(e);

// node.next = head;

// head = node;

//方式二

add(0,e);

}

//在链表的index(0-based)位置添加新的元素e

public void add(int index,E e){

if(index < 0 || index > size)

throw new IllegalArgumentException(“Add failed. Illegal index.”);

Node prev = dummyHead;

for (int i = 0; i < index; i++)

prev = prev.next;

prev.next = new Node(e,prev.next);

size ++;

}

//在链表末尾添加新的元素e

public void addLast(E e){

add(size,e);

}

//在链表的index(0-based)位置添加新的元素e

public E get(int index){

if(index < 0 || index > size)

throw new IllegalArgumentException(“Get failed. Illegal index.”);

Node cur = dummyHead.next;

for (int i = 0; i < index; i++)

cur = cur.next;

return cur.e;

}

//获得链表的第一个元素

public E getFirst(){

return get(0);

}

//获取链表的最后一个元素

public E getLast(){

return get(size - 1);

}

//在链表的index(0-based)位置添加新的元素e

public void set(int index,E e){

if(index < 0 || index > size)

throw new IllegalArgumentException(“Set failed. Illegal index.”);

Node cur = dummyHead.next;

for (int i = 0; i < index; i++)

cur = cur.next;

cur.e = e;

}

//查找链表中是否有元素e

public boolean contains(E e){

Node cur = dummyHead.next;

while (cur != null){

if(cur.e.equals(e))

return true;

cur = cur.next;

}

return false;

}

//从链表中删除Index(0-based)位置的元素,返回删除的元素

public E remove(int index){

if(index < 0 || index > size)

throw new IllegalArgumentException(“Remove failed. Illegal index.”);

Node prev = dummyHead;

for (int i = 0; i < index; i++)

prev = prev.next;

Node retNode = prev.next;

prev.next = retNode.next;

retNode.next = null;

size --;

return retNode.e;

}

//从链表中删除第一个位置的元素

public E removeFirst(){

return remove(0);

}

//从链表中删除最后一个位置的元素

public E removeLast(){

return remove(size - 1);

}

@Override

public String toString() {

StringBuilder res = new StringBuilder();

for (Node cur = dummyHead.next;cur != null; cur= cur.next)

res.append(cur + “->”);

res.append(“Null”);

return res.toString();

}

}

4.2.7 结果测试:

public static void main(String[] args) {

LinkedList linkedList = new LinkedList<>();

//添加元素 0-4

for (int i = 0; i < 5 ; i++) {

linkedList.addFirst(i);

System.out.println(linkedList);

}

//添加第二个元素添加 666

linkedList.add(2,666);

System.out.println(linkedList);

//删除第二个元素 666

linkedList.remove(2);

System.out.println(linkedList);

//删除第一个元素

linkedList.removeFirst();

System.out.println(linkedList);

//删除最后一个元素

linkedList.removeLast();

System.out.println(linkedList);

}

打印结果:

0->Null

1->0->Null

2->1->0->Null

3->2->1->0->Null

4->3->2->1->0->Null

4->3->666->2->1->0->Null

4->3->2->1->0->Null

3->2->1->0->Null

3->2->1->Null

四、链表时间复杂度分析


| 功能 | 时间复杂度 |

| — | — |

| 增加 | O(n) |

| 删除 | O(n) |

| 修改 | O(n) |

| 查询 | O(n) |

对于增加和删除来说,如果是对链表头进行操作,那么就是 O(1) 级别的复杂度,对于查询来说,也是一样

五、链表应用


5.1 使用栈实现链表
[](ht

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

tps://blog.csdn.net/qq_14996421/article/details/103250536)5.1.1 接口类:

/**

  • @program: Data-Structures

  • @ClassName Stack

  • @description:

  • @author: lyy

  • @create: 2019-11-20 21:51

  • @Version 1.0

**/

public interface Stack {

int getSize();

boolean isEmpty();

void push(E e);

E pop();

E peek();

}

5.1.2 实现类:

import com.lyy.datasty.Mystack.Stack;

//链表栈实现

public class LinkedListStack implements Stack {

private LinkedList1 list;

public LinkedListStack(){

list = new LinkedList1<>();

}

@Override

public int getSize() {

return list.getSize();

}

@Override

public boolean isEmpty() {

return list.isEmpty();

}

@Override

public void push(E e) {

list.addFirst(e);

}

@Override

public E pop() {

return list.removeFirst();

}

@Override

public E peek() {

return list.getFirst();

}

@Override

public String toString() {

StringBuilder res = new StringBuilder();

res.append("Stack:top ");

res.append(list);

return res.toString();

}

}

5.1.3 运行结果:

public static void main(String[] args) {

LinkedListStack stack = new LinkedListStack<>();

for (int i = 0; i < 5; i++) {

stack.push(i);

System.out.println(stack);

}

stack.pop();

System.out.println(stack);

}

5.1.4 结果打印:

Stack:top 0->Null

Stack:top 1->0->Null

Stack:top 2->1->0->Null

Stack:top 3->2->1->0->Null

Stack:top 4->3->2->1->0->Null

Stack:top 3->2->1->0->Null

5.2 使用链表实现队列
5.2.1 接口类

/**

  • @program: Data-Structures

  • @ClassName Queue

  • @description:

  • @author: lyy

  • @create: 2019-11-21 21:54

  • @Version 1.0

**/

public interface Queue {

int getSize();

boolean isEmpty();

void enqueue(E e);

E dequeue();

E getFront();

}

5.2.2 实现类

public class LinkedListQueue implements Queue{

//设计私有的内部类,对于用户来说不需要知道链表底层实现,

// 不需要知道node这个节点,对用户屏蔽编码实现的底层实现

private class Node{

public E e;

public Node next;//public 可以在LinkedList随意操作

public Node(E e, Node next){

this.e = e;

this.next = next;

}

public Node(E e){

this(e,null);

}

public Node(){

this(null,null);

}

@Override

public String toString() {

return e.toString();

}

}

private Node head,tail;

private int size;

public LinkedListQueue(){

head = null;

tail = null;

size = 0;

}

@Override

public int getSize() {

return size;

}

@Override

public boolean isEmpty() {

return size == 0;

}

@Override

public void enqueue(E e) {

if(tail == null){

tail = new Node(e);

head = tail;

}else{

tail.next = new Node(e);

tail = tail.next;

}

size ++;

}

@Override

public E dequeue() {

if(isEmpty())

throw new IllegalArgumentException(“Cannot dequeue from an empty queue.”);

Node retNode = head;

head = head.next;

retNode.next = null;

if(head == null)

tail = null;

size --;

return retNode.e;

}

@Override

public E getFront() {

if(isEmpty())

throw new IllegalArgumentException(“queue is empty.”);

return head.e;

}

@Override

public String toString() {

StringBuilder res = new StringBuilder();

res.append("Queue:front ");

Node cur = head;

while (cur != null) {

res.append(cur + “->”);

cur = cur.next;

}

res.append(“Null tail”);

return res.toString();

}

}

5.2.2 测试类

public static void main(String[] args) {

LinkedListQueue queue = new LinkedListQueue<>();

for (int i = 0; i < 10; i++) {

queue.enqueue(i);

System.out.println(queue);

if(i % 3 ==2){

queue.dequeue();

System.out.println(queue);

}

}

}

打印结果:

Queue:front 0->Null tail

Queue:front 0->1->Null tail

Queue:front 0->1->2->Null tail

Queue:front 1->2->Null tail

Queue:front 1->2->3->Null tail

Queue:front 1->2->3->4->Null tail

Queue:front 1->2->3->4->5->Null tail

Queue:front 2->3->4->5->Null tail

Queue:front 2->3->4->5->6->Null tail

Queue:front 2->3->4->5->6->7->Null tail

Queue:front 2->3->4->5->6->7->8->Null tail

Queue:front 3->4->5->6->7->8->Null tail

Queue:front 3->4->5->6->7->8->9->Null tail

六、更多链表结构


6.1 双链表

在这里插入图片描述

代码:

class Node{

E e;

Node next,prev;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值