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

问题:《数据结构与算法分析(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 
#include 
#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<data<<" ";
        h=h->next;
    }
    cout<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,所以把原来链表的元素插入进去不会产生死循环的现象

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