编程导航算法第一关 |链表的基础

今天也是算法通关村刚开始,学习了链表。

首先,链表是一种最基本的结构,我们通常在收到一个链表的时候只有一个指向链表头的指针head,因为链表就是通过头指针来寻找其他结点的。

链表中的每个结点都存在它的数据和指向下一个节点的指针。

在遍历链表中,我们只需要在while循环中让它一直next就可以了,代码如下。

public static int getLength(Node head) {
    int length = 0;
    Node node = head;
    while (node != null) {
        length++;
        node = node.next;
    }
    return length;
}

在插入链表时,三种情况,表头插入,中间插入,结尾插入。

1. 表头插入,由于我们是通过头指针来寻找其他结点的,所以我们只需要将头结点改为新结点就可以了,head = nodeInsert;

2. 中间插入,我们需要在目标节点的前一个位置停下来,这里定义为cur,需要让cur.next=新结点,再让new.next=cur.next,这样就让cur结点的下一个结点是新结点,新结点下一个结点为原来cur.next,这样就实现了插入;

3.结尾插入,只要将尾结点指向新结点就可以了。

public static Node insertNode(Node head, Node nodeInsert, int position) {
    // 需要判空,否则后面可能会有空指针异常
    if (head == null) {
        return nodeInsert;
    }
    //越界判断
    int size = getLength(head);
    if (position > size + 1 || position < 1) {
        System.out.println("位置参数越界");
        return head;
    }

    //在链表开头插入
    if (position == 1) {
        nodeInsert.next = head;
		//return nodeInsert;
        //上面return还可以这么写:
        head = nodeInsert;
        return head;
    }

    Node pNode = head;
    int count = 1;
    while (count < position - 1) {
        pNode = pNode.next;
        count++;
    }
    nodeInsert.next = pNode.next;
    pNode.next = nodeInsert;

    return head;
}

链表删除,同样是三种情况,考虑表头,中间,表尾

1. 删除表头结点,只要执行head=head.next就行了

2. 删除中间结点,找到位置后,将cur.next指针的值更新为cur.next.next就可以解决

3. 删除表尾结点,只需要让表尾结点的前驱节点的next=null就可以了

public static Node deleteNode(Node head, int position) {
    if (head == null) {
        return null;
    }
    int size = getLength(head);
    if (position > size || position <= 0) {
        System.out.println("输入的参数有误");
        return head;
    }

    if (position == 1) {
        // head.next就是链表的新head
        return head.next;
    }
    Node preNode = head;
    int count = 1;
    while (count < position) {
        preNode = preNode.next;
        count++;
        Node curNode = preNode.next;
        preNode.next = curNode.next;
    }
    return head;
}

其实,我觉得链表就是通过表头就可以想查哪个结点就查哪个结点,不管是要对链表中的结点增删改查,都需要通过头结点来next。

双向链表

每个结点都是有数据域,指向前一个结点的指针,指向后一个结点的指针,这样的话移动元素会更方便。但是相对来说,代码也就更多了,更复杂,但是道理都是一样的。

在链表中间插入的时候,这里定义cur为要插入结点位置的前一个结点,需要先将当前结点的下一个结点的前一个结点等于新加入的结点,再让新结点的下一个结点设为现在cur的下一个结点,这样就完成了第一步,让新结点和要插入位置后边的结点联系起来了,然后让cur的下一个结点设为新插入的节点,再让当前节点的前一个结点设为cur,这样就让新加入的节点和cur结点联系起来了。关键代码为:

//某个结点的后部插入
public void insertAfter(int key, int data) {
    DoubleNode newDoubleNode = new DoubleNode(data);
    DoubleNode current = first;
    while ((current != null) && (current.data != key)) {
        current = current.next;
    }
    //若当前结点current为空
    if (current == null) {      
         //current为null有两种情况 一种是链表为空,一种是找不到key值
        if (isEmpty()) {       //1、链表为空       
            //则插入第一个结点(其实可以调用其它的Insert方法)
            first = newDoubleNode;       
            //first和last均指向该结点(第一个结点)
            last = newDoubleNode;                    
        } else {
            //2、找不到key值
            last.next = newDoubleNode;        
            newDoubleNode.prev = last;    //则在链表尾部插入一个新的结点
            last = newDoubleNode;
        }
    } else {      //第三种情况,找到了key值,分两种情况
        if (current == last) {        
            //1、key值与最后结点的data相等
            newDoubleNode.next = null;       
            //由于newNode将是最后一个结点,则将last指向newNode
            last = newDoubleNode;                    
        } else {
            //2、两结点中间插入
            newDoubleNode.next = current.next; 
            current.next.prev = newDoubleNode;    
        }                                        
        current.next = newDoubleNode;       //将当前结点的next域指向newNode
        newDoubleNode.prev = current;       //将新结点的previous域指向current
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值