#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 999
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status; //Status 是函数返回值类型,其值是函数结果状态代码。
typedef int ElemType; //ElemType 为可定义的数据类型,此设为int类型
int index[maxn],t;
typedef struct LNode
{
ElemType data; //结点的数据域
struct LNode *next; //结点的指针域
}LNode,*LinkList; //LinkList为指向结构体LNode的指针类型
Status InitList_L(LinkList &L){ //算法2.5 单链表的初始化
//构造一个空的单链表L
L=new LNode; //生成新结点作为头结点,用头指针L指向头结点
L->next=NULL; //头结点的指针域置空
return OK;
}
Status ListInsert_L(LinkList &L,int i,ElemType &e){ //算法2.8 单链表的插入
//在带头结点的单链表L中第i个位置之前插入元素e
int j;
LinkList p,s;
p=L;j=0;
while(p && j<i-1){p=p->next;++j;} //寻找第i-1个结点
if(!p||j>i-1) return ERROR; //i大于表长+1或者小于1
s=new LNode; //生成新结点s
s->data=e; //将结点s的数据域置为e
s->next=p->next; //将结点s插入L中
p->next=s;
return OK;
}//ListInsert_L
void CreateList_F(LinkList &L,int n){ //算法2.10 前插法创建单链表
//逆位序输入n个元素的值,建立到头结点的单链表L
LinkList p;
L=new LNode;
L->next=NULL; //先建立一个带头结点的空链表
cout<<"请输入 "<<n<<" 个数(以空格隔开,按回车结束):";
for(int i=n;i>0;--i){
p=new LNode; //生成新结点
cin>>p->data; //输入元素值
p->next=L->next;L->next=p; //插入到表头
}
}//CreateList_F
void CreateList_L(LinkList &L,int n){ //算法2.11 后插法创建单链表
//正位序输入n个元素的值,建立到头结点的单链表L
LinkList r,p;
L=new LNode;
L->next=NULL; //先建立一个带头结点的空链表
r=L; //尾指针r指向头结点
cout<<"请输入 "<<n<<" 个数(以空格隔开,按回车结束):";
for(int i=0;i<n;i++){
p=new LNode; //生成新结点
cin>>p->data; //输入元素值
p->next=NULL;r->next=p; //插入到表尾
r=p; //r指向新的尾结点
}
}//CreateList_L
Status Getindex(LinkList L, int i){
//int counts=0;
memset(index,-1,sizeof(index));
LinkList P;
P=L->next;
t=0;
int j=0;
while(P)
{ //cout<<1<<endl;
while(P->data!=i&&P->next)
{P=P->next;j++;/*cout<<1<<endl;*/}
if(P->data==i) {j++;/*cout<<"j"<<j<<endl;*/;index[t++]=j;}
if(!P->next) {break;}
P=P->next;
}
return t;
//return OK;
}//根据输入的值返回对应编号
Status GetMax(LinkList L,ElemType &e){
LinkList r,p;
r=L->next;
int j=0;
int maxs=0;
while(r)
{
if(r->data>maxs)
{
maxs=r->data;
}
r=r->next;
j++;
}
e=maxs;
cout<<"最大值:"<<maxs<<endl;
int t=Getindex(L,e);
return t;
//Getindex(L,e);
}
Status DeleteList(LinkList &L,int i){
LinkList p,q;
p=new LNode;
int j=0;
p=L;
while(p->next&&i-1>j){
p=p->next;
j++;
}
if(!p->next||i-1<j)
return ERROR;
q=p->next;
p->next=q->next;
delete(q);
return OK;
}
void ObList(LinkList &L){
LinkList p,q,r;
p=L->next;
q=p->next;
r=L->next;
r->next=NULL;
if(!p||!q)
return;
while(q){
L->next=q;
p=q->next;
q->next=r;
r=q;
q=p;
}
}
Status GetElem(LinkList L, int i, ElemType &e){
LinkList P;
int j=0;
P=L;
while(j<i&&P)
{P=P->next;j++;}
if(j>i||!P)
return ERROR;
e=P->data;
return OK;
}//根据输入的编号返回该编号的值
void Deleteitem(LinkList &L,int i){
LinkList p;
p=L->next;
int j=1;
//cout<<"p:"<<p->data<<endl;
while(p)
{ //cout<<1<<endl;
while(p->data!=i&&p->next)
{p=p->next;j++;/*cout<<"J1"<<j<<endl;*/}
if(p->data==i) {p=p->next;DeleteList(L,j);}///要注意删除后,j不再对应是删除后元素在链表中的位置
if(!p->next) {break;}
}
}
int main()
{
int i,n,choose;
ElemType x;
LinkList L,p;
choose=-1;
while(choose!=0)
{
cout<<"******************************************************************************\n";
cout<<" 1. 建立空链表; 2. 在表中输入指定个数的数据元素\n";
cout<<" 3. 在第i个元素的前插入一个元素; 4. 逐个显示表中数据元素\n";
cout<<" 5. 查找位序为i的元素,返回其值; 6. 依值查找,返回其位序\n";
cout<<" 7. 删除表中第i个元素; 8. 返回值最大的元素及其在表中位置\n";
cout<<" 9. 就地逆置; 10. 删除表中所有值为item的数据元素\n";
cout<<" 0. 退出\n";
cout<<"*******************************************************************************\n";
cout<<"请选择:";
cin>>choose;
switch(choose)
{
case 1: //建立一个单链表
if(InitList_L(L))
cout<<"成功建立链表!\n\n";
break;
case 2: //使用后插法创建单链表
cout<<"请输入一个数,代表元素的个数:";
cin>>n;
CreateList_L(L,n);
cout<<"成功创建链表!\n\n";
break;
case 3: //单链表的插入
cout<<"请输入两个数,分别代表插入的位置和插入数值(用空格间隔,最后回车):";
cin>>i>>x; //输入i和x,i代表插入的位置,x代表插入的数值
if(ListInsert_L(L,i,x))
cout<<"成功将"<<x<<"插在第"<<i<<"个位置\n\n";
else
cout<<"插入失败!\n\n";
break;
case 4: //单链表的输出
cout<<"现在链表里的数分别是:";
p=L->next;
i=0;
while(p)
{
i++;
cout<<p->data<<",";
p=p->next;
}
cout<<"共有"<<i<<"个元素。"<<endl<<endl;
break;
case 5:
cout<<"输入你要查找的元素的位序: ";
cin>>i;//输入i,代表要查找的位序
//cout<<GetElem(L, i, x)<<endl;
if(GetElem(L, i, x))
cout<<"您要查找的元素:"<<x<<endl;
else cout<<"ERROR"<<endl;
break;
case 6:
{int k;
cout<<"输入您要查找位序的元素:"<<endl;
scanf("%d",&k);
int n=Getindex(L,k);
cout<<"一共有"<<n<<"个"<<endl<<"位序分别是:";
for(int i=0;i<t;i++)
printf("%d%c",index[i],i==t-1?'\n':' ');}
//else cout<<"not found"<<endl;
break;
case 7:
cout<<"请输入你要删除的元素的编号:";
cin>>i;
if(DeleteList(L,i))
cout<<"成功删除第"<<i<<"个元素"<<endl;
else
cout<<"删除失败"<<endl;
break;
case 8:
{cout<<"返回元素中的最大值及其位置";
int t=GetMax(L,x);
/*cout<<"最大值:"<<x;*/
cout<<"位置:"<<t<<endl;}
for(int i=0;i<t;i++)
printf("%d%c",index[i],i==t-1?'\n':' ');
break;
case 9:
cout<<"就地逆置"<<endl;
ObList(L);
break;
case 10:
cout<<"输入您想要删光的元素:";
cin>>i;
Deleteitem(L,i);
cout<<"已删光所有元素"<<endl;
//else
// cout<<"不存在该元素"<<endl;
break;
}
}
return 0;
}
就地逆置的另一种写法,思路更清晰(推荐),上面的代码都是自己想的和写的,有一些地方觉得虽然实现了,但是思路不够清晰。
void reverse(LinkList &L)
{
//单链表为空或只有头结点或只有一个元素,不用进行逆置操作
if(L==NULL||L->next==NULL||L->next->next==NULL) return;
LNode* p=L->next->next;//令p指向线性表中第2个元素a2
L->next->next=NULL;//令线性表中第1个元素a1的next为空
while(p)
{
LNode* q=p->next;
//将p插入到头结点之后
p->next=L->next;
L->next=p;
p=q;//继续访问下一个元素
}
}