Java面试复习(数据结构-单链表)

目录

1.链表的概念和分类

1.1概念

1.2分类

1.3 链表具体结构

1.4 链表与顺序表的区别(面试常考)

2.单链表的增删查改

2.1单链表的数据插入

2.1.1 头插法

2.1.2 尾插法

2.1.3  任意位置插入

2.2 单链表的打印

2.3单链表数据的查找

2.4获取单链表的数据个数

2.5 单链表数据的删除

2.5.1 删除链表中第一次出现的目标值

2.5.2 删除所有和key值相等的节点(面试可能会考,重点)

2.5.3 单链表的销毁


1.链表的概念和分类

1.1概念

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

链表结构包括两部分:一是数据域,二是指针域,称为引用域!其中,数据域用来存放数据,它可以是基本数据类型,也可以是引用数据类型,不论是前者还是后者,在面向对象编程当中通通叫做对象;引用域用来存放地址,这个地址指向下一个链表结点或前一个链表结点,对于引用域的引用变量可以是一个也可以是两个,只有一个引用变量,则该链表为单链表,有两个引用变量,一个指向前驱结点,另一个指向后继结点,则该链表为双链表。
 

1.2分类

链表主要依据以下三点进行分类:

1.带头与不带头  2.循环与不循环  3.单链表和双链表

因而可将链表分为8类: 带头非循环单链表、 不带头非循环单链表、带头循环单链表、不带头循环单链表、带头非循环双链表、不带头非循环双链表、不带头循环双链表

1.3 链表具体结构

定义 链表中的数据值为val,引用域指向下一节点的变量名为next,指向前一个节点的引用变量名为prev,单链表的最后一个节点next指向null,双链表的最后一个节点与第一个节点的prev指向null

1.4 链表与顺序表的区别(面试常考)

顺序表的物理结构是连续的,逻辑结构也是连续的,它的优点是支持随机访问,获取和修改一个数据非常地方便,缺点是插入,删除元素不方便,空间利用率不高,可能存在大量空间浪费。
链表的物理结构不连续,逻辑结构连续,它完美解决了顺序表的缺点,它的优点是插入,删除元素方便,空间利用率高,随取随用,缺点是访问不方便,不支持随机访问。

2.单链表的增删查改

基本方法列表

public class SList {

    public ListNode head;
    //头插法
    public void addFirst(int data){
    }
    //尾插法
    public void addLast(int data){
    }
    //任意位置插入,第一个数据节点为0号下标
    public void 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 display(){
    }
    //链表销毁
    public void clear(){
	}
}

2.1单链表的数据插入

基本变量和结构方法的准备

class ListNode {//ListNode代表一个节点
    public int val;
    public ListNode next;
    public ListNode(int val) {
        this.val = val;//该构造方法是为了让下面new一个对象时,直接给val进行赋值
    }
}
public class MylinkedList {
        //head为链表的头引用
        public ListNode head;
//各类方法。。。。

}

2.1.1 头插法

头插法:在第一个节点前面插入数据,即将插入的数据的节点和后一个节点连接,并将头引用指向新插入的数据节点,主要实现的代码 (1)node.next=head.next  (2)head=node

代码实现:

 //头插法
        public void addFist(int data) {
            ListNode node = new ListNode(data);
            node.next=this.head;
            this.head=node;
//            if (this.head == null) {
//                this.head = node;
//            }else {
//                node.next = head;
//                this.head = node;
//            }
        }

2.1.2 尾插法

尾插法则需要先遍历链表找到最后一个节点,即cur.next为null,然后再将新节点插入到最后一个节点后

    public void addLast(int val){
        ListNode node=new ListNode(val);
        if(this.head==null){
            this.head=node;
        }
        ListNode cur=this.head;
        while(cur.next!=null){
            cur=cur.next;
        }
        cur.next=node;
    }

2.1.3  任意位置插入

//找到打算插入值的index-1位置节点地址,在index-1和index位置中间
    //插入,则插入的值的节点位置刚好为index
    public ListNode findIndex(int index){
        ListNode cur=this.head;
        if(index-1!=0){
            cur=cur.next;
            index--;
        }
        return cur;
    }
    public void addIndex(int index,int data){
        if(index<0||index>size()){
            System.out.println("位置不合法");
            return;
        }
        //如果index=0则头插法
        if(index==0){
           addFirst(data);
           return;
        }
        //如果index=size则尾插
        if(index==size()){
            addLast(data);
            return;
        }
        //index-1位置的节点
        ListNode cur=findIndex(index);
        //定义一个node节点并将data存入其中
        ListNode node=new ListNode(data);
        //新添加的节点和后面节点链接
        node.next=cur.next;
        //前面节点和node链接
        cur.next=node;
    }

2.2 单链表的打印

 public void display(){
        ListNode cur=this.head;
        while(cur!=null){
            System.out.println(cur.val+" ");
            cur=cur.next;
        }
        System.out.println();
    }

2.3单链表数据的查找

 public boolean contains(int key){
        ListNode cur=this.head;
        while(cur!=null){
            if(cur.val==key){
                return true;
            }
            cur=cur.next;
        }
        return false;
    }

2.4获取单链表的数据个数

 public int size() {
        int count = 0;
        ListNode cur = head.next;
        while (cur != null) {
            cur = cur.next;
            count++;
        }
        return count;
    }

2.5 单链表数据的删除

2.5.1 删除链表中第一次出现的目标值

   //删除第一次出现关键字为key的节点
    public void remove(int key){
        if(this.head==null){
            System.out.println("单链表为空,不能删除");
            return;
        }
        //如果头节点为要删除的节点
        if(this.head.val==key){
            this.head=this.head.next;
            return;
        }
        //cur表示要删除的节点
        ListNode cur=this.head.next;
        ListNode prev=this.head;
        while(cur!=null){
            if(cur.val==key){
                //如果cur为要删除的节点,则可将前驱与cur。next链接
                prev.next=cur.next;
                return;
            }
            //如果还没有找到,则cur的值赋值给前驱,cur值向后走寻找要删除的值
            prev=cur;
            cur=cur.next;
        }
        System.out.println("未找到目标节点!");
    }

2.5.2 删除所有和key值相等的节点(面试可能会考,重点)

//删除所有链表中的目标值
    public void removeAllkey(int key){
        if(this.head==null){
            return;
        }
        //当头节点的值和key值相等时
        while(this.head.val==key){
            //让头节点的值变为下一节点的值,由于是删除所有,因而
            //还需要继续往下去寻找
            this.head=this.head.next;
            if(this.head==null){
                return;
            }
        }
        //继续向后寻找
        ListNode cur=this.head.next;
        ListNode prev=this.head;
        while(cur!=null){
            if(cur.val==key){
                prev.next=cur.next;
                //和上面的区别是找到后cur仍需要继续向后走
                cur=cur.next;
            }
            else{
                //如果没有找到则前驱prev和待删除的cur往后走
                prev=cur;
                cur=cur.next;
            }
        }
    }

2.5.3 单链表的销毁

   // 清空链表
   public void clear(){
    while(this.head!=null){
        ListNode curNext=head.next;
        this.head=null;
        this.head=curNext;
    }
   }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值