(单链表的应用)反转链表

题目来源:PIPIOJ 1271 反转链表

【问题描述】

反转长度为N的单链表从位置 L 到 R 的子段。请在常数空间复杂度下使用一趟扫描完成反转。

【输入输出】

1.输入:
	第一行三个整数N,L,R,1<=L<=R<=N
	接下来N个数表示N个节点的值
	
2.输出:
	输出反转后的单链表节点值

【样例】

样例输入:
	5 2 4
	1 2 3 4 5
	
样例输出:
	1 4 3 2 5

【算法思路】

单链表元素的逆置与顺序表不同,顺序表由于随机存取的特性很容易通过下标进行头尾互换从而完成逆置,但是单链表由于无法随机存取,也没有下标可用因此单链表的逆置问题会比顺序表复杂得多。

而本题要求逆置链表第 [L, R] 上的结点,那么我们的思路就是把 L~R 这一段单独提取出来,然后用头插法就能实现这段元素的翻转,然后再将断开后的前后两段进行拼接。而提取这段元素可以通过一个flag进行标记,如果遍历到的元素是[L, R] 上的结点,则标记flag=1,否则flag=0。这样所有被标记为flag=1的元素就可以用头插法插入到一个新的链表了。

【算法描述】

#include 
using namespace std;

//定义单链表结点
typedef struct LNode
{
    int data;
    struct LNode *next;
}LNode;

//反转链表中第m~n个结点,并返回表头指针
LNode* Reverse(LNode* head, int m, int n)   
{
    LNode *preL = NULL; //preL指向第m个结点的前一个结点
    LNode *L = NULL;    //L指向第m个结点
    LNode *sufR = NULL; //sufR指向第n个结点的后一个结点
    LNode *q;
    LNode *H;	//提取出来的元素的表头结点
    H = (LNode*)malloc(sizeof (LNode));
    int c = 1;  //c表示当前为第几个结点
    int flag = 0;   //flag表示现在是否处于[m,n]

    if (m == 1)     //如果从第一个结点开始翻转
        flag = 1;

    //遍历整个链表
    for (LNode *p=head; p; c++)
    {
        if (c == m-1)   //当遍历到了m的前一个结点
            preL = p;
        else if (c == m)    //当遍历到了第m个结点
        {
            L = p;
            flag = 1;
        }
        else if (c == n+1)  //当遍历到了n的后一个结点,此时flag=0
        {
            sufR = p;
            flag = 0;
        }

        //使用头插法,放到H为头指针的链表上
        if (flag == 1)
        {
            q = p->next;    //q用来暂存下一个需要插入的元素
            p->next = H->next;
            H->next = p;
            p = q;
        }
        else
            p = p->next;
    }
    L->next = sufR; //将反转后的那一段与后段拼接
    if (preL)   //如果存在m-1个结点
    {
        preL->next = H->next;
        return head;
    }
    else
        return H->next;
}


int main()
{
    int N,L,R;
    cin >> N >> L >> R;
    LNode *head;    //定义一个表头结点
    head = (LNode*)malloc(sizeof (LNode));  //为表头结点分配存储空间
    head->next = NULL;
    LNode *p, *s;   //s用来指向新申请的结点,p始终指向head的终端结点
    p = head;
    //尾插法构造单链表
    for (int i=0; i<N; ++i)
    {
        s = (LNode*)malloc(sizeof (LNode));
        cin >> s->data;
        p->next = s;
        p = p->next;
    }
    p->next = NULL;

    head->next = Reverse(head->next, L, R);

    LNode *r = head;
    for (int i=0; i<N; ++i)
    {
        r = r->next;
        cout << r->data << " ";
    }

你可能感兴趣的:(#,线性表,链表,数据结构,算法)