|
|
#include<iostream>
|
|
|
using namespace std;
|
|
|
#include<stdlib.h>
|
|
|
|
|
|
#define OK 1
|
|
|
#define ERROR 0
|
|
|
|
|
|
typedef int status;
|
|
|
typedef int ElemType;
|
|
|
|
|
|
//用结构体定义一个单链表
|
|
|
typedef struct LNode
|
|
|
{
|
|
|
ElemType data; //存储链表的数据元素
|
|
|
struct LNode *next; //定义一个结构体指针用来指向下一个链表结点的地址
|
|
|
}LNode,*Linklist; //这里定义的 Linklist ==LNode *;
|
|
|
|
|
|
//---------单链表的基本操作------------
|
|
|
//一、单链表的初始化以及正序输入
|
|
|
status Initlist(Linklist &L,int n)
|
|
|
{
|
|
|
Linklist q,p;
|
|
|
L=(Linklist)malloc(sizeof(LNode)); //为单链表分配头结点,但注意头结点不是链表的第一个结点
|
|
|
L->next=NULL; //头结点的指针域指向第一个结点的地址
|
|
|
q=L; //让q指向链表的尾指针;
|
|
|
cout<<"请输入单链表的元素:"<<endl;
|
|
|
for(int i=0;i<n;i++)
|
|
|
{
|
|
|
p=(Linklist)malloc(sizeof(LNode));
|
|
|
cin>>p->data;
|
|
|
q->next=p; //将q的指针域指向p
|
|
|
q=p; //让p成为新的q
|
|
|
}
|
|
|
q->next=NULL;
|
|
|
return OK;
|
|
|
}
|
|
|
|
|
|
//二、单链表的插入
|
|
|
status Insertlist(Linklist &L,int i,ElemType e)
|
|
|
{
|
|
|
Linklist p,s;
|
|
|
int j=0;
|
|
|
p=L;
|
|
|
while(p&&j<i-1)
|
|
|
{
|
|
|
p=p->next;
|
|
|
j++;
|
|
|
} //此while循环用于查找插入位置的前一个结点
|
|
|
if(!p||j>i-1)
|
|
|
return ERROR; //此if语句判断查找是否失败
|
|
|
s=(Linklist)malloc(sizeof(LNode)); //为插入的数据分配一个结点
|
|
|
if(!s)
|
|
|
return ERROR;
|
|
|
s->data=e;
|
|
|
s->next=p->next; //将p的指针域传给s的指针域
|
|
|
p->next=s; //然后将p的指针域指向s结点
|
|
|
return OK;
|
|
|
}
|
|
|
|
|
|
//三、单链表的删除
|
|
|
status Deletelist(Linklist &L,int i,ElemType &e)
|
|
|
{
|
|
|
Linklist p,q;
|
|
|
int j=0;
|
|
|
p=L;
|
|
|
while(p&&j<i-1)
|
|
|
{
|
|
|
p=p->next;
|
|
|
j++;
|
|
|
}
|
|
|
if(!(p->next)||j>i-1) //当如果p的下一个结点为空时,则删除错误
|
|
|
return ERROR;
|
|
|
q=p->next; //将要删除的结点用q指向
|
|
|
e=q->data; //用e返回删除结点的元素
|
|
|
p->next=q->next; //将q的指针域传给p;
|
|
|
free(q);
|
|
|
return OK;
|
|
|
}
|
|
|
|
|
|
//四、单链表的查找
|
|
|
status GetElem(Linklist L,int e,int &i)
|
|
|
{
|
|
|
Linklist p=L->next;
|
|
|
if(p==NULL)
|
|
|
return ERROR;
|
|
|
i=1;
|
|
|
while(p)
|
|
|
{
|
|
|
if(p->data==e)
|
|
|
{
|
|
|
return i; //如果在链表中找到该元素,则输出其位序
|
|
|
}
|
|
|
p=p->next; //否则继续下移查找
|
|
|
i++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//五、单链表的输出
|
|
|
status Printf(Linklist L)
|
|
|
{
|
|
|
Linklist p;
|
|
|
p=L->next; //让p表示单链表的第一个结点
|
|
|
while(p)
|
|
|
{
|
|
|
cout<<p->data<<" ";
|
|
|
p=p->next; //输出第一个结点数据后,p后移一位
|
|
|
}
|
|
|
cout<<endl;
|
|
|
return OK;
|
|
|
}
|
|
|
|
|
|
//单链表的逆置(头插法)
|
|
|
status Reservelist(Linklist &L)
|
|
|
{
|
|
|
Linklist p,q; //定义两个指针,p是当头结点与第一个结点断开时,而设立的指针,指向第一个结点
|
|
|
p=L->next; //而q的作用也是与p类似。
|
|
|
L->next=NULL; //将头结点与第一个结点的链接断开
|
|
|
while(p)
|
|
|
{
|
|
|
q=p->next; //q是为了指向剩余未逆置的元素地址
|
|
|
p->next=L->next;
|
|
|
L->next=p; //以上两条语句是将第一个结点逆置插入
|
|
|
p=q; //然后将q赋给p;
|
|
|
}
|
|
|
return OK;
|
|
|
}
|
|
|
|
|
|
//单链表的清空
|
|
|
status Clearlist(Linklist &L)
|
|
|
{
|
|
|
Linklist p,q;
|
|
|
p=L->next;
|
|
|
while(p)
|
|
|
{
|
|
|
p=q;
|
|
|
q=p->next; //设立一个q指向剩下的结点,之后一个一个清空。
|
|
|
free(p);
|
|
|
}
|
|
|
L->next=NULL;
|
|
|
cout<<"此链表已清空"<<endl;
|
|
|
return OK;
|
|
|
}
|
|
|
|
|
|
//单链表的销毁
|
|
|
status Destroylist(Linklist &L)
|
|
|
{
|
|
|
Linklist p;
|
|
|
while(L)
|
|
|
{
|
|
|
p=L;
|
|
|
L=L->next;
|
|
|
free(p);
|
|
|
}
|
|
|
cout<<"此链表已销毁。"<<endl;
|
|
|
return OK;
|
|
|
}
|
|
|
|
|
|
int main()
|
|
|
{
|
|
|
Linklist L;
|
|
|
int n,i;
|
|
|
ElemType e;
|
|
|
cout<<"请输入单链表的长度:"<<endl;
|
|
|
cin>>n;
|
|
|
Initlist(L,n);
|
|
|
cout<<"单链表为:"<<endl;
|
|
|
Printf(L);
|
|
|
|
|
|
cout<<"请输入要插入第几个结点、插入的元素:"<<endl;
|
|
|
cin>>i>>e;
|
|
|
Insertlist(L,i,e);
|
|
|
cout<<"插入元素后单链表为:"<<endl;
|
|
|
Printf(L);
|
|
|
|
|
|
cout<<"请输入要删除的结点位置:"<<endl;
|
|
|
cin>>i;
|
|
|
Deletelist(L,i,e);
|
|
|
cout<<"删除的元素为:"<<e<<endl;
|
|
|
cout<<"删除元素后单链表为:"<<endl;
|
|
|
Printf(L);
|
|
|
|
|
|
cout<<"请输入要查找的结点元素:";
|
|
|
cin>>e;
|
|
|
GetElem(L,e,i);
|
|
|
cout<<e<<"对应的结点位置为:"<<i<<endl;
|
|
|
cout<<endl;
|
|
|
|
|
|
cout<<"单链表逆置后输出为:"<<endl;
|
|
|
Reservelist(L);
|
|
|
Printf(L);
|
|
|
|
|
|
Clearlist(L);
|
|
|
Destroylist(L);
|
|
|
return OK;
|
|
|
}
|
|
|
|