反转单链表并验证(详解)

单链表优点:

  1. 可以动态增加和删除。
  2. 不需要定义初始大小。

点链表缺点:

  1. 不能随机访问。需要逐个遍历直到找到目标项。
  2. 用到动态内存分配和指针,代码复杂度提升,内存泄漏和内存段错误风险提升。
  3. 开销大较大,因为是动态分配内存。而且每项需要存储一个额外的指针。

定义单链表:

    ------------------------------              ------------------------------
    |              |             |            \ |              |             |
    |      val     |     next    |--------------|      val     |     next    |
    |              |             |            / |              |             |
    ------------------------------              ------------------------------单链表的每一个节点包含两部分:数据val和指向下一个节点的指针next。
1 typedef struct list_node ListNode;
2
3 struct list_node{
4     int val;
5     struct list_node* next;
6 };

初始化单链表:

关键在两个指针:newNode和curNode。

newNode是用来指向新建节点。而curNode则是指向链表尾节点。

如果head为NULL,那么head和curNode都将指向newNode。

如果head不为NULL,那么只需将尾节点的next指向newNode,即curNode->next=newNode;,同时需记录新链表的尾节点,即curNode=newNode;。

以此类推,直到数组的最后一个元素的值插入到链表的尾部。

 1 ListNode* InitLinkedList(ListNode* head, int* array, int size)
 2 {
 3     head = NULL;
 4     ListNode* newNode = NULL;
 5     ListNode* curNode = NULL;
 6     for (int i = 0; i < size; i++)
 7     {
 8         newNode = malloc(sizeof(ListNode));
 9         newNode->val = array[i];
10         newNode->next = NULL;
11
12         if (head == NULL)
13         {
14             head = newNode;
15             curNode = newNode;
16         }
17         else
18         {
19             curNode->next = newNode;
20             curNode = newNode;
21         }
22     }
23
24     return head;
25 }

打印单链表:

1 void PrintLinkedList(ListNode* head)
2 {
3     while (head != NULL)
4     {
5         printf("%d ", head->val);
6         head = head->next;
7     }
8     printf("\n");
9 }

反转单链表:

反转的关键在于借助于两个额外指针p和q。同时记录q的next节点。因为q的next节点需要指向p,如果不先记录q的next节点,链表会就此断开。

接下来就是p和q的逐步向前推进,直到q指向NULL,而此时p刚好是反转后的链表的头节点。

 1 ListNode* ReverseLinkedList(ListNode* head)
 2 {
 3     ListNode* p = NULL;
 4     ListNode* q = head;
 5
 6     while (q != NULL)
 7     {
 8         ListNode* nextq = q->next;
 9         q->next = p;
10         p = q;
11         q = nextq;
12     }
13
14     return p;
15 }

主函数:

 1 int main(void)
 2 {
 3     ListNode* root = NULL;
 4     int numArray[] = { 1, 2, 3, 4, 5 };
 5
 6     root = InitLinkedList(root, numArray, 5);
 7     printf("original linked list:\n");
 8     PrintLinkedList(root);
 9
10     root = ReverseLinkedList(root);
11     printf("reversed linked list:\n");
12     PrintLinkedList(root);
13
14     getchar();
15     return 0;
16
17 }

结果截图:

解题的要点在于有一个清晰的思路,然后就是将逻辑用代码来实现。

 
时间: 2024-07-28 16:52:56

反转单链表并验证(详解)的相关文章

JavaScript 身份证号有效验证详解及实例代码

JavaScript 身份证号有效验证详解及实例代码 这篇文章主要介绍了JavaScript 身份证号有效验证详解及实例代码的相关资料,需要的朋友可以参考下 JavaScript验证身份证号 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 <%@ page language="jav

递归、非递归 反转单链表

定义链表结构 struct ListNode { int val; ListNode *next; ListNode(int v) : val(v), next(NULL) {} }; 非递归反转单链表 ListNode* reverse(ListNode *root) { if (root == NULL || root->next == NULL) return root; ListNode *cur = root->next; root->next = NULL; while (c

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

js正则实现二代身份证号码验证详解

js正则实现二代身份证号码验证详解 根据[中华人民共和国国家标准 GB 11643-1999]中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成.排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码. 地址码表示编码对象常住户口所在县(市.旗.区)的行政区划代码. 出生日期码表示编码对象出生的年.月.日,其中年份用四位数字表示,年.月.日之间不用分隔符. 顺序码表示同一地址码所标识的区域范围内,对同年.月.日出生的人员

JavaScript表单序列化的方法详解

本文介绍下,在javascript中实现表单序列化的方法,通过实例加深理解,有需要的朋友参考下吧. 在JavaScript中,可以利用表单字段的type属性,连同name和value属性一起实现对表单的序列. 首先,我们来了解下在表单提交期间,浏览器是怎样将数据发送给服务器的.对表单字段的名称和值进行URL编码,使用和号(&)分割.不发送禁用的表单字段.只发送勾选的复选框和单选按钮.不发送type为"reset"和"button"的按钮.多选择框中的每个选中

【LeetCode-面试算法经典-Java实现】【092-Reverse Linked List II(反转单链表II)】

[092-Reverse Linked List II(反转单链表II)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Reverse a linked list from position m to n. Do it in-place and in one-pass. For example: Given 1->2->3->4->5->NULL, m = 2 and n = 4, return 1->4->3->2->

算法题:反转单链表

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:存在一个单链表,头指针为head,实现单链表的反转Node *Reverse(Node *head).  该算法的求解办法有很多,如: 方法1:先顺序变量单链表,将结点保存到栈中,在从栈中弹出结点,重新建立一个新的单链表: 方法2:用<剑指offer>里面给出的算法,用三个指针来实现: 方法3:采用递归实现,是方法2的递归实现形式. 本文主要给出方法2和方法3,在给出具体的代码之前,先要注意几个问题:          (1)如果hea

boboJquery表单插件ajaxForm用法详解

插件主要的方法: ajaxFormajaxSubmitformToArrayformSerialize fieldSerializefieldValueclearFormclearFieldsresetForm 示例代码: 1 // wait for the DOM to be loaded 2 $(document).ready(function() {  3    // bind 'myForm' and provide a simple callback function   4    $

STL list链表的用法详解(转)

本文以List容器为例子,介绍了STL的基本内容,从容器到迭代器,再到普通函数,而且例子丰富,通俗易懂.不失为STL的入门文章,新手不容错过! 0 前言 1 定义一个list 2 使用list的成员函数push_back和push_front插入一个元素到list中 3 list的成员函数empty() 4 用for循环来处理list中的元素 5 用STL的通用算法for_each来处理list中的元素 6 用STL的通用算法count_if()来统计list中的元素个数 7 使用count_i