数据结构和算法之单向链表六:链表的反转以及链表节点的删除

  在前面介绍了关于链表的一系列问题,这里我们在介绍一下关于单向链表的反转这个比较具有代表性的算法。在进行反转的时候一定要记住多画图,多去理解在链表进行反转的时候它对于地址的改变,这和数组的数据对换具有很大的不一致。

  

public Node reverseList(Node head){
       //判断链表是否为空或者只有一个节点
       if(head == null || head.next == null){
             return head;
       }
       //准备三个节点
       Node next = null;//保存当前节点的下一个节点
       Node reverse = null;//反转以后链表的头节点
       Node current = head;//当前正在进行反转的节点
       while(current != null){
             //保存当前节点的下一个节点
             next = current.next;
             //将头结点转换给当前节点的下一个节点
             current.next = reverse;
             //给头结点赋值
             reverse = current;
             //将当前节点后移
             current = next;
       }
       return reverse;
}

  重要的事情说三遍,地址转换很重要!地址转换很重要!地址转换很重要!

  关于单向链表的删除问题为什么我会在这里单独拿出来进行说一下,这是属于单向链表的基本操作,但是我们可不可以思考一个问题。在前面我们说了地址转换这个东西,如果我们在进行删除的时候,将要删除的节点的下一个节点赋值给删除的节点,然后再把下一个节点变为空,那么我们是不是就实现了删除的操作。代码如下:

public boolean deleteNode(Node delete){
       //判断链表是否为空
       if(head == null){
            return false;
       }
       //判断该节点是否是尾节点
       if(delete.next == null){
            delete = null;
             return true;
       }
       //找到需要删除节点的下一个节点
       Node next = delete.next
       //将下一节点的值赋给删除节点,并清空删除节点信息
       delete = next;
       next = null;
       return true;
}

  删除的代码只是提供了思路,代码需要自己去重写。关于这么写的好处那是显而易见的,我们可以在删除的时候只花销O(1)的时间,如果常规思路我们去获取删除节点的前一个节点我们花费的时间可远远不止这些。当然这是建立在链表里必有这个节点的前提下,如果链表节点是否存在需要我们自己去判断那自然是无法完成,因为这样便利一个链表的时间是O(N)。

  

时间: 2024-10-09 23:53:00

数据结构和算法之单向链表六:链表的反转以及链表节点的删除的相关文章

题目:输入一个链表的头结点,反转该链表,并返回反转后链表的头结点。

题目:输入一个链表的头结点,反转该链表,并返回反转后链表的头结点.链表结点定义如下: struct ListNode { int       m_nKey; ListNode* m_pNext; }; c语言实现 /* File : rlink.c Author : Date : 2015/4/4 platform : windows7 x86_64 version : 1.0 Function : 反转一个链表 */ #include <stdio.h> #include <stdli

数据结构与算法学习-单向链表的实现

链表(Chain本文所说链表均为单向链表,以下均简称单向链表)实际上是由节点(Node)组成的,一个链表拥有不定数量的节点.而向外暴露的只有一个头节点(Head),我们对链表的所有操作,都是直接或者间接地通过其头节点来进行的. 节点(Node)是由一个需要储存的对象及对下一个节点的引用组成的.也就是说,节点拥有两个成员:储存的对象.对下一个节点的引用. 这样说可能大家不是很明白,我贴一张图大家可能更容易理解. package LinkedList; /** * <p><strong>

数据结构与算法(三)--单向链表

有的时候,处于内存中的数据并不是连续的.那么这时候,我们就需要在数据结构中添加一个属性,这个属性会记录下面一个数据的地址.有了这个地址之后,所有的数据就像一条链子一样串起来了,那么这个地址属性就起到了穿线连结的作用. 相比较普通的线性结构,链表结构的优势是什么呢?我们可以总结一下: (1)单个节点创建非常方便,普通的线性内存通常在创建的时候就需要设定数据的大小 (2)节点的删除非常方便,不需要像线性结构那样移动剩下的数据 (3)节点的访问方便,可以通过循环或者递归的方法访问到任意数据,但是平均的

C语言:【单链表】逆置反转单链表

#include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int DataType; typedef struct SListNode {     DataType data;     struct SListNode* next; }SListNode; SListNode* BuyNode(DataType x) {     SListNode* next = (SListNode*)malloc

数据结构和算法之单向链表二:获取倒数第K个节点

我们在做算法的时候或多或少都会遇到这样的问题,那就是我们需要获取某一个数据集的倒数或者正数第几个数据.那么今天我们来看一下这个问题,怎么去获取倒数第K个节点.我们拿到这个问题的时候自然而然会想到我们让链表从末尾开始next   K-1 次不就是第K-1个节点了么,但是必须要注意一点,这是单向链表.那么这时候的解决思路或许就会出现分歧,大多数人都会想到我们遍历一下链表,获取链表的长度,然后再减去 K 长度的节点,那么我们这个链表的最后一个节点就是原链表的倒数第K个节点:我们看一下实现代码: /**

《Java数据结构与算法》笔记-CH5-链表-5用双端链表实现队列

1 //用双端链表实现队列 2 /** 3 * 节点类 4 */ 5 class LinkQ { 6 private long data; 7 public LinkQ next; 8 9 public LinkQ(long d) { 10 this.data = d; 11 } 12 13 public String toString() { 14 return String.valueOf(this.data); 15 } 16 } 17 /** 18 * 双端链表类 19 */ 20 cl

数据结构与算法小结——排序(六)

3.2 快速排序 快速排序综合性能优越,其主要思想在于找一个pivotvalue,通过不断的比较.交换,将序列变成pivotvalue前的值都比它小,在其后的值都比它大:然后,再对pivotvalue前面的序列和后面的序列分别使用同样的方法得到具有该性质的序列.....不断递归调用至最底层即排好序.其基本流程如图 1所示. 图 1 快速排序基本流程 分析快速排序的时间复杂度,可以画出一个二叉树,二叉树的结点即是每一层递归选用的pivotvalue.显然,如果pivotvalue选择得当,使得递归

数据结构与算法-链表反转带头节点

1.输入一个链表的头结点,反转该链表,并返回反转后链表的头结点.链表结点定义如下:    struct ListNode{      int       m_nKey;      ListNode* m_pNext;};分析:这是一道广为流传的微软面试题.由于这道题能够很好的反应出程序员思维是否严密,在微软之后已经有很多公司在面试时采用了这道题. 为了正确地反转一个链表,需要调整指针的指向.与指针操作相关代码总是容易出错的,因此最好在动手写程序之前作全面的分析.在面试的时候不急于动手而是一开始做

大公司面试经典数据结构与算法题C#解答

几个大公司(IBM.MicroSoft and so on)面试经典数据结构与算法题C#解答 1.链表反转 我想到了两种比较简单的方法 第一种是需要开一个新的链表,将原链表的元素从后到前的插入到新链表中(也就是原链表第一个元素被插入成新链表的最后一个元素). 第二种是不需要开新的链表,而是逐步反转原链表中元素的指向,例如: 原链表是 1->2->3->4->null  被  逐步修改为 ①2->1->null.3->4->null ②3->2->