例题2-9:请设计算法,将带有头结点的链表进行就地逆置。
有两种写法,
一种是把链表进行头插法,进行逆置
另一种方法就是把链表设置三变量不断往后指来移动。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#define LElemType int
using namespace std;
typedef struct LNode{
LElemType data;
struct LNode *next;
LNode ( LElemType Data=0, struct LNode *Next=NULL){
data=Data;
next=Next;
}
}LNode,*LinkList;
void InitLinkList(LinkList &L){
L=new LNode ;
}
void CreateLinkList_Tail(LinkList &L, int n=0){ //尾插法
L=new LNode ;
LinkList pre=L,tmp;
LElemType Data;
for (int i=0;i<n;i++){
printf("请输入第%d个元素的data : \n",i+1);
cin>>Data;
tmp=new LNode (Data);
pre->next=tmp;
pre=tmp;
}
}
void CreateLinkList_Head(LinkList &L, int n=0){ //头插法
L=new LNode;
LinkList Tail,tmp;
LElemType Data;
for(int i=0;i<n;i++){
printf("请输入第%d个元素的data : \n",i+1);
cin>>Data;
tmp=new LNode(Data);
tmp->next=L->next;
L->next=tmp;
}
}
int ListIsEmpty(LinkList &L){
if(L->next){
return 1;
}
return 0;
}
int ListLength(LinkList &L){
int Len=0;
LinkList p=L->next;
while(p){
//printf("%d\n",p->data);
Len++;
p=p->next;
}
return Len;
}
void OutputLinkList(LinkList &L){
printf("\n");
LinkList p=L->next;
while(p){
//cout<<p->data<<endl;
printf("%d%c",p->data,p->next==NULL?'\n':' ');
p=p->next;
}
}
void GetElem(LinkList L,int pos,LElemType &e){
int i=1;
LinkList p=L->next;
while(p&&i<pos){
i++;
p=p->next;
}
if( i > pos || !p){
printf(" \"GetElem\" pos is error\n");
return ;
}
e=p->data;
}
LElemType LocateElem(LinkList L,LElemType e){
int j=1;
LinkList p=L->next;
while(p&&p->data!=e){
j++;
p=p->next;
}
if(!p){
printf("\" LocateElem \" not exist E : %d \n",e);
return 0;
}
return j;
}
void ListInsert(LinkList &L,int i,LElemType e){
int j=0;
LinkList p=L,s;
while(p&&j<i-1){
j++;
p=p->next;
}
if(!p||j>i-1){
printf("\" ListInsert \"index : %d error!\n",i);
return;
}
s=new LNode(e,p->next);
p->next=s;
}
void ListDelete(LinkList &L, int i ,LElemType &e){
int j=0;
LinkList p=L,s;
while(p->next&&j<i-1){
j++;
p=p->next;
}
if(!(p->next)||j>i-1){
printf("\" ListDelete \" index: %d error!\n",i);
return ;
}
s=p->next;
e=s->data;
p->next=s->next;
delete s;
}
void Array_List(LinkList &L,int a[],int n){
InitLinkList(L);
LinkList p,Pre=L;
for(int i=0;i<n;i++){
p=new LNode(a[i],NULL);
Pre->next=p;
Pre=p;
}
}
void Reverse(LinkList &L){ //头插法
LinkList p=L->next,s;
L->next=NULL;
while(p){
s=p->next;
p->next=L->next;
L->next=p;
p=s;
}
}
void Reverse_2(LinkList &L){
LinkList p,q,r;
q=NULL; p=L->next;
InitLinkList(L);
while(p){
//printf("%d\n",p->data);
r=q; q=p; p=p->next;
q->next=r;
}
L->next=q;
}
void Reverse_3(LinkList &L,int S,int E){
LinkList p1,p2,p3,p4,p=L,s,t;
int len=ListLength(L),cnt=0;
while(p){
if(cnt+1==S) {p1=p;}
else if(cnt==S) {p2=p;}
if(cnt==E) {p3=p;}
else if(cnt-1==E) {p4=p;}
p=p->next;
cnt++;
}
//printf("%d %d %d %d\n",p1->data,p2->data,p3->data,p4->data);
p=p2->next;
s=p2;
p3->next=NULL;
p2->next=NULL;
while(p){
t=p->next;
p->next=s;
s=p;
p=t;
}
p1->next=p3;
p2->next=p4;
}
int main()
{
LinkList L;
int a[]={1,2,3,4,5,6};
Array_List(L,a,6);
OutputLinkList(L);
Reverse(L);
OutputLinkList(L);
Reverse_2(L);
OutputLinkList(L);
int S,E,len=ListLength(L);
printf("允许区域逆置链表操作: %d\n",len);
do{
printf("请输入一个区域的左右端点:\n");
scanf("%d%d",&S,&E);
}while(!(1<=S&&S<len&&1<=E&&E<len&&S<E));
Reverse_3(L,S,E);
OutputLinkList(L);
}