数据结构与算法(c++)——反转链表

算法概述:要求实现将一条单向链表反转并考虑时间复杂度。

算法分析:

数组法(略):

  将列表元素逐个保存进数组,之后再逆向重建列表

  点评:实现逻辑最简单,需要额外的内存开销。

移动指针:

  通过三个指针逐个从链表头开始逐一反转链表元素的指针

  点评:不需要额外的内存开销,会改变原始链表。

递归:

  以递归的方式首先找到链表尾部,再逐一反转指针

  点评:不需要额外的内存开销,不会改变原始链表。

算法实现:

构建链表结构

/* 节点结构 */
struct NODE
{
    int data;
    struct NODE* next;
};

/* 添加元素-压栈 */
void push(NODE** head, int dat) {
    struct NODE* new_node = new NODE();
    new_node->data = dat;
    new_node->next = *head;
    *head = new_node;
}

/* 添加元素-添加 */
void add(NODE** head, int dat) {
    struct NODE* new_node = new NODE();
    new_node->data = dat;
    new_node->next = NULL;
    if (*head != NULL) {
        struct NODE* temp = *head;
        while (temp->next != NULL) {
            temp = temp->next;
        }
        temp->next = new_node;
    }
    else {
        *head = new_node;
    }
}

移动指针

/* 反转列表 */
void reverse(NODE** head) {
    struct NODE* pre = NULL;
    struct NODE* cur = *head;
    struct NODE* nxt;
    while (cur != NULL) {
        // 反转指针
        nxt = cur->next;
        cur->next = pre;
        // 移动指针
        pre = cur;
        cur = nxt;
    }
    *head = pre;
}

递归

/* 反转列表-复制原表返回反转表 */
NODE* reverse(NODE* head) {
    if (head == NULL || head->next == NULL) {
        return head;
    }
    NODE* new_head = reverse(head->next);
    // 反转指针
    head->next->next = head;
    head->next = NULL;
    return new_head;
}

打印链表

/* 打印队列 */
void print(NODE* head) {
    NODE* temp = head;
    while (temp != NULL) {
        std::cout << temp->data << std::endl;
        temp = temp->next;
    }
}

>>完整代码

时间: 2024-11-03 21:56:15

数据结构与算法(c++)——反转链表的相关文章

java数据结构与算法之双链表设计与实现

转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/53047590 出自[zejian的博客] 关联文章: 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) ??上一篇文章分析顺序表和单链表,本篇就接着上篇继续聊链表,在单链表

数据结构与算法JavaScript (三) 链表

数据结构与算法JavaScript (三) 链表 我们可以看到在javascript概念中的队列与栈都是一种特殊的线性表的结构,也是一种比较简单的基于数组的顺序存储结构.由于 javascript的解释器针对数组都做了直接的优化,不会存在在很多编程语言中数组固定长度的问题(当数组填满后再添加就比较困难了,包括添加删除, 都是需要把数组中所有的元素全部都变换位置的,javascript的的数组确实直接给优化好了,如 push,pop,shift,unshift,split方法等等…) 线性表的顺序

数据结构与算法系列:链表

链表定义: 1 // 链表结点 2 struct ListNode 3 { 4 int m_nValue; 5 ListNode* m_pNext; 6 }; 常见问题: #include <iostream> #include <stack> // 输入数据 int Read() { int value; std::cin >> value; return value; } // 创建链表 ListNode* CreateList(int nLen) { ListNo

算法:反转链表。

题目描述 输入一个链表,反转链表后,输出新链表的表头. 思路 定义当前head,前序节点pre,后续节点next:依次遍历所有节点,将所有节点的next指向前一个节点. package LG.nowcoder; /** * @Author liguo * @Description 输入一个链表,反转链表后,输出新链表的表头. * 思路:定义当前head,前序节点pre,后续节点next: * 依次遍历所有节点,将所有节点的next指向前一个节点 * @Data 2018-08-13 23:24

算法-leetcode-206.反转链表

题目链接:反转链表 主要是弄清楚几个变量该怎么交换值即可: c语言版本: /** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* reverseList(struct ListNode* head){ //可以在开始的时候处理下空链表和只有一个元素的情况,直接返回就行,循环也能处理这两种情况,所以就省掉了对应的

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

在前面介绍了关于链表的一系列问题,这里我们在介绍一下关于单向链表的反转这个比较具有代表性的算法.在进行反转的时候一定要记住多画图,多去理解在链表进行反转的时候它对于地址的改变,这和数组的数据对换具有很大的不一致. public Node reverseList(Node head){ //判断链表是否为空或者只有一个节点 if(head == null || head.next == null){ return head; } //准备三个节点 Node next = null;//保存当前节点

数据结构与算法JavaScript描述——链表

1.数组的缺点 数组不总是组织数据的最佳数据结构,原因如下. 在很多编程语言中,数组的长度是固定的,所以当数组已被数据填满时,再要加入新的元素就会非常困难. 在数组中,添加和删除元素也很麻烦,因为需要将数组中的其他元素向前或向后平移,以反映数组刚刚进行了添加或删除操作. 然而,JavaScript 的数组并不存在上述问题,因为使用splice() 方法不需要再访问数组中的其他元素了. JavaScript 中数组的主要问题是,它们被实现成了对象,与其他语言(比如C++ 和Java)的数组相比,效

[算法练习] 反转链表

题目说明: 输入一个链表的头结点,反转该链表,并返回反转后链表的头结点.链表结点定义如下:struct ListNode{     int m_nKey;     ListNode* m_pNext;}; 程序代码: #include <gtest/gtest.h> #include <vector> using namespace std; struct ListNode { int m_nKey; ListNode* m_pNext; }; ListNode* ReverseL

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

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