#include<iostream>
#include<cstring>
#include <set>
#include <map>
#include <ctime>
#include <bitset>
#include <sstream>
#include <algorithm>
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>//getch()的头文件
#include<vector>
#include<queue>
#include<stack>
using namespace std;
//单链表的结点LNode,并且在定义这个数据结构的时候定义指向其指针的命名为LinkList 即: Lnode *p 等同于 LinkList p
typedef struct LNode{ // 定义单链表结点类型
int data; // 数据域
struct LNode* next; // 指针域
}LNode,*LinkList;
LNode* CreateList(){// 头插法创建单链表
LNode *p=(LinkList)malloc(sizeof(LNode));// 开辟一个等同于结点所需大小的空间
p->next=NULL;
int temp;
cout<<"输入数值,将使用头插法创建一个新的单链表,数值-1代表输入结束"<<endl;
cin>>temp;
while(-1!=temp){
LNode *s = (LinkList) malloc(sizeof(LNode));
s->data=temp;
s->next=p->next;
p->next=s;
cin>>temp;
}
return p;
}
void PrintList(LinkList &L){// 传进来的是指针的引用
LinkList t = (LinkList)malloc(sizeof(LNode));
t=L;
while(NULL !=t->next ){
t=t->next;// 因为头插法的头结点不携带信息,因此首先要对该链表的结点后移操作;
cout<<t->data<<"\t";
}
cout<<endl;
}
void ReverseList(LinkList &L) {// 类似链表的输出,这里的参数自然也是指针的引用
// 采用不创建额外的单链表的单链表逆置
// 实现方法:记录头结点的下一个结点的位置;并且这个结点将会成为最后的一个结点
LinkList p= (LinkList) malloc(sizeof(LNode)); // 生成结点
p=L->next;// p指向的位置就是L的下一个结点,并且这个结点不会再发生改变
// 此时再需要一个移动的结点即可 不妨设为temp
LinkList temp = (LinkList) malloc (sizeof (LNode));
while(p->next!=NULL){// 这样也可以排除只有除头结点外 只有一个结点的情况
temp=p->next;
p->next=temp->next;
temp->next=L->next;
L->next=temp;
}
cout<<"转置成功!"<<endl;
}
LinkList newListReverse(LinkList &L){
// 与上面的方法不同,该方法会建立一个新的链表,新链表同样使用头插法对原链表进行转置
// 创建一个新的链表的头结点
LinkList k=(LinkList) malloc(sizeof(LNode));
k->next=NULL;
// 创建一个移动结点
LinkList j=(LinkList) malloc(sizeof(LNode));
j=L;
while(j->next!=NULL){
j=j->next;// 因为头结点没有存储任何数据,因此要对其进行首次的移动
LinkList temp= (LinkList) malloc(sizeof(LNode));// 生成转置链表中的一个结点
temp->data=j->data;
temp->next=k->next;
k->next=temp;
}
delete L; // 删除原来链表中指向的空间
cout<<"转置成功!"<<endl;
return k;
}
int main()
{
LNode *p = CreateList();
PrintList(p);
cout<<"内部转置"<<endl;
ReverseList(p);
PrintList(p);
cout<<"借助新链表转置"<<endl;
p=newListReverse(p);
PrintList(p);
return 0;
}
运行结果: