数据结构与算法-单链表-线性表转置

本文介绍了一种基于C++实现的单链表转置算法,详细解释了如何通过编程将单链表中的元素顺序反转,并提供了完整的源代码示例及运行结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:《数据结构与算法分析(C++语言版)》p58 五、2
已知一个如下图所示的带头结点的单链表head(注:若头指针名是head,则把单链表称为表head),其存储结构为:

typedef struct Lnode{
    ElemType data;
    struct Lnode *next;
}Lnode,*LinkList;

题图
请编写一个线性表的转置算法。线性表转置是指将 (a1,a2,...,an) ( a 1 , a 2 , . . . , a n ) 变为 (an,an1,...,a1) ( a n , a n − 1 , . . . , a 1 )



问题分析

根据题意,首先要创建一个带头结点的单链表,单链表包含头结点,每个结点包括数据与data和指针域*next,为了简化操作,可设单链表的元素为数字1~10,为此需要创建初始化单链表的函数,首先将头结点指向NULL,然后用循环连续创建10个新结点,并将他们依次相连,并赋值;为了能够显示出转置前后的区别,需要编写一个打印函数,需要从首元结点(Head->next)依次遍历到最后一个结点(p->next=NULL),并用cout语句输出,注意需要加上分隔符;最后为了实现该题的核心功能,需要创建一个转置函数(Reverse),其中需考虑第一次操作后续操作不同的情况,否则会出现第一个结点(即转置后的最后一个结点)出现自己指向自己的死循环;最后在主程序中调用相应的函数,可以选择在原单链表进行操作,也可重新建立一个单链表进行操作。

程序代码

#include <iostream>
#include <stdlib.h>
#define ElemType int
using namespace std;
typedef struct Lnode{
    ElemType data;
    struct Lnode *next;
}Lnode,*LinkList;

int InitList(LinkList h) {
    Lnode *p;
    h->next=NULL;//初始化头结点
    for(int i=0; i<10; i++) {
        p=new Lnode;
        p->data=i+1;//依次加一
        p->next=NULL;
        h->next=p;
        h=p;
    }p->next=NULL;//最后指向空

}

int ListPrint(LinkList h) {
    h=h->next;//指向首元结点
    while(h) {
        cout<<h->data<<" ";
        h=h->next;
    }
    cout<<endl;
}

int Reverse(LinkList h){
    Lnode *p,*q;
    int j=0;//计数器,用来区别第一次操作和后续操作
    p=h->next;
    while(p!=NULL){
        q=p->next;//q结点指向p结点的后一个
        if(j==0)//如果是第一次操作
        p->next=NULL;//首个结点(转置后的最后一个结点)指向空,避免打印时出现死循环
        else
        p->next=h->next;//指向新的首元结点
        h->next=p;//首元结点指向新的结点,即把位序更大的元素挪到前面
        p=q;//结点后移
        j++;//计数器+1
    }

}
int main() {
    Lnode *head,*head2,*a,*b;
    InitList(head);
    ListPrint(head);
    Reverse(head);
    ListPrint(head);

//head2=new Lnode;    使用新的单链表进行存储
//  a=head->next;
//  head2->next=NULL;
//  while(a){
//      b=a->next;
//      a->next=head2->next;
//      head2->next=a;
//      a=b;
//  } 
//  a=head2->next;
//  ListPrint(head2);
}

运行结果

在原链表中区别对待第一次操作的正确输出:

1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1

在原链表中区别对待第一次操作的错误输出:

1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ……

注意事项

  • 也可以在Reverse函数中不使用计数器j,即需要先对第一次循环特别操作,让第一个结点先指向NULL,然后再将后续的操作进入循环。
  • 使用新的单链表进行存储时,则不需要进行特殊操作,因为新链表的头指针本来指向的就是NULL,所以把原来链表的元素插入进去不会产生死循环的现象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值