颠倒一个链表的顺序 C++

首先我们定义一个头结点:

    struct Node{
        int data;
        Node*next;
    };

接下来我们写一个函数来创建一个链表:

    //a是一个数组,n代表数组元素的个数
    Node*createLinkList(int a[],int n)
    {
        if(a==NULL||n==0)
            return NULL;
        Node*L,*T=NULL;
        for(int i=0;i<n;i++)
        {
            if(i==0)
            {L=new Node;
            L->data=a[i];
            L->next=NULL;
            T=L;
            }else
            {
                Node*s=new Node;
                s->data=a[i];
                s->next=NULL;
                T->next=s;
                T=s;//结点移动
            }
        }
        return L;
    }

下面就开始我们的翻转方法部分

1)首先我们先用递归方法来进行处理

(1)如果一个链表为空链表,那么他的逆序还是为空

(2)如果一个链表中只有一个节点,那么他的逆序就是这个链表本身.

(3)如果一个链表的长度大于一,那么我们做如下递归.

把当前链表的除了头节点L之外的剩余节点组成的链表逆序,也就是递归调用,并得到剩余链表逆序后的头结点p,

此时将L的下一个节点的的next指向L, 并将L的next指针置空.然后返回p.

(简单来说,先是一层层寻找,找到尾结点返回给p,然后返回上一层,这时最后一个节点为L->next,将L->next的next指向现在第二层的L,然后再把L的next置空,即完成了第一次翻转,然后再返回给p;把这次的两个结点看成最后一个,然后在倒数第三层重复反转,最后完成整个反转)

    Node*reverseLinkList(Node*L)
    {
        if(L==NULL) return NULL;
        if(L->next==NULL) return L;  

            Node*p=reverseLinkList(L->next);
            L->next->next=L;//倒数第一个指向倒数第二个
            L->next=NULL;//倒数第二个指针置空  

        return p;
    }

2)第二种方法就不进行递归进行翻转,然而我们直接在最后翻转会出现断链,进而不能进行连续遍历,所以我们可以定义三个结点,pnow指向当前结点,pre指向它的前置,nex指向它的后驱,首先令pnow的下一个指针指向nex,然后令pnow的next拆掉并连接pre,进行翻转,这时pnow和nex之间是断开的,然后将pnow设置为前驱pre,将nex设置为pnow,即完成了一段翻转,重复到完毕即可。

    Node*noreverseLinkList(Node*L)
    {
        if(L==NULL||L->next==NULL) return L;
        Node*pnow=L,*pre=NULL,*nex=NULL,*tail=NULL;
        while(pnow!=NULL)
        {
            nex=pnow->next;
            if(NULL==nex){
                tail=pnow;}
            pnow->next=pre;
            pre=pnow;
            pnow=nex;  

        }  

        return tail;
    }

为了验证,我们还要写一个显示函数:

    void display(Node*L)
    {  Node*p=L;
        if(p==NULL) return ;
        while(p!=NULL)
        {
            cout<<p->data<<" ";
            p=p->next;
        }
        cout<<endl;  

    }

完整代码:

include<iostream>
using namespace std;
struct Node{
    int data;
    Node*next;
};
//a是一个数组,n代表数组元素的个数
Node*createLinkList(int a[],int n)
{
    if(a==NULL||n==0)
        return NULL;
    Node*L,*T=NULL;
    for(int i=0;i<n;i++)
    {
        if(i==0)
        {L=new Node;
        L->data=a[i];
        L->next=NULL;
        T=L;
        }else
        {
            Node*s=new Node;
            s->data=a[i];
            s->next=NULL;
            T->next=s;
            T=s;//结点移动
        }
    }
    return L;
}
void display(Node*L)
{  Node*p=L;
    if(p==NULL) return ;
    while(p!=NULL)
    {
        cout<<p->data<<" ";
        p=p->next;
    }
    cout<<endl;  

}
Node*reverseLinkList(Node*L)
{
    if(L==NULL) return NULL;
    if(L->next==NULL) return L;  

        Node*p=reverseLinkList(L->next);
        L->next->next=L;//倒数第一个指向倒数第二个
        L->next=NULL;//倒数第二个指针置空  

    return p;
}
Node*noreverseLinkList(Node*L)
{
    if(L==NULL||L->next==NULL) return L;
    Node*pnow=L,*pre=NULL,*nex=NULL,*tail=NULL;
    while(pnow!=NULL)
    {
        nex=pnow->next;
        if(NULL==nex){
            tail=pnow;}
        pnow->next=pre;
        pre=pnow;
        pnow=nex;  

    }  

    return tail;
}  

int _tmain(int argc, _TCHAR* argv[])
{
    int a[] = {1,2,3,4,5,6};
    int b[] = {1,2,3,4,5,6,7};
    Node *L = createLinkList(a,6);
    display(L);  

    display(noreverseLinkList(L));
    Node *A = createLinkList(b,7);
    display(reverseLinkList(A));
    system("pause");
    return 0;
}

谢谢阅读。详细解读:(有图理解)http://blog.csdn.net/zhaoruixiang1111/article/details/49932603

时间: 2024-10-09 14:40:46

颠倒一个链表的顺序 C++的相关文章

线性链表之顺序表

顺序表中数据元素的存储地址是其序号的线性函数,只要确定了存储顺序表的起始地址(即 基地址),计算任意一个元素的存储地址的时间是相等的,具有这一特点的存储结构称为[随机存储]. 使用的基本数据结构:数组 特点:顺序存取,随机访问. /* Name: SeqList Copyright: 1.0 Author: Johnny Zen Date: 04/06/17 21:51 Description: 线性链表之顺序表 *//* Chinese:顺序(线性)表 English:SeqList*/#in

有序链表和顺序表

通过捕捉键盘动作来进行交互,头文件为conio.h,是console input output的缩写,捕捉用户键盘按键的函数为getch(),通过键值码可以找到对应的按键. #include<stdio.h> #include<string.h> #include<stdlib.h> #include<conio.h> #include<windows.h> #define MAX 5000 struct List { int num; List

优点和阵列的缺点,并且一个链表

排列,定在存储器中的连续空间.名单,存储器地址可以是不连续,每一个链表的节点包含原来的内存和下一个节点的信息(单向的一个,双向链表的话,会有两个). 数组优于链表的: 1.内存空间占用的少,由于链表节点会附加上一块或两块下一个节点的信息.可是数组在建立时就固定了.所以也有可能会由于建立的数组过大或不足引起内存上的问题. 2.数组内的数据可随机訪问.但链表不具备随机訪问性.这个非常easy理解.数组在内存里是连续的空间.比方假设一个数组地址从100到200,且每一个元素占用两个字节,那么100-2

设计鲁棒性的方法:输入一个链表的头结点,逆序遍历打印该链表出来

之前有过整理链表等的概念和基本算法.比较重要的是插入,删除,遍历,建表(尾插法,头插法) 回忆链表尾部插入结点:  1 #include <iostream> 2 using namespace std; 3  4 typedef struct Node{ 5     int data;//数据域 6     Node *next;//指针域 7 } Node, *List; 8  9 //在单链表的末位添加一个结点10 void addNode(List *head, int value)1

算法总结之 判断一个链表是否是回文结构

给定一个链表的头节点head,判断是否是回文结构 1->2->1 返回true 进阶: 如果链表长度N,时间复杂度O(N) 额外空间O(1) 方法一 利用栈结构(需要额外空间) 从左到右遍历,一次压栈.   这样的到的  从栈顶到栈底的节点值出现顺序会与原链表从左到右的值出现顺序相反. 废话不多说,上代码: package TT; import java.util.Stack; public class Test92 { public class Node{ public int value;

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

题目:输入一个链表的头结点,反转该链表,并返回反转后链表的头结点.链表结点定义如下: 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

26、输入一个链表,反转链表后,输出链表的所有元素。

输入一个链表,反转链表后,输出链表的所有元素. 思路:  ListNode next = null;//用来保存待反序的第一个节点(head 和 next节点) ListNode pre = null;//用来保存已经反序的第一个结点 next = head.next;//首先记录当前节点的下一个节点,(保存起来) //先用next保存head的下一个节点的信息,保证单链表不会因为失去head节点的原next节点而就此断裂 head.next = pre;//让当前节点指向前一个节点,因为要反序

实现一个链表和队列

import java.text.SimpleDateFormat; import java.util.Calendar; import org.apache.log4j.Logger; /* * 实现一个泛型链表类接口, 1.链表增加一个节点, 2.指定位置增加一个节点 3.删除指定位置的节点 4.删除某种内容的所有节点 加上日志 * */ public class LinkMe { public static void main(String args[]){ //BasicConfigur

输入一个链表,从尾到头打印链表每个节点的值

题目描述: 输入一个链表,从尾到头打印链表每个节点的值. 输入描述: 输入为链表的表头 输出描述: 输出为需要打印的"新链表"的表头 用栈处理: /** *    public class ListNode { *        int val; *        ListNode next = null; * *        ListNode(int val) { *            this.val = val; *        } *    } * */ import