注重于程序健壮性的单链表,在学习单链表是我的方法是画图,当你理解所学,在写代码时画图是帮你梳理思路的一个很好方法
一下是我的代码,仅供参考,我写的有配套的实验报告——对于代码的解释以及一些我在学习中出现的问题,如有需要评论区留下邮箱(可能不会及时回复,望谅解)
#include <iostream>
#include <stdlib.h>
#define TRUE 1;
#define FALSE 0;
#define ERROR -1;
#define LEN sizeof(Lnode)
using namespace std;
typedef struct Lnode
{
int data;
struct Lnode *next;
}Lnode,*Linklist;
typedef int Status;
typedef int Elemtype;
void title();
Status InitList(Linklist *L); //创建链表
Status DestroyList(Linklist *L); //销毁链表
Status ListLength(Linklist L); //链表长度
Status GetElement(Linklist L,int i,Elemtype *e);//返回指定位置的元素值
Status LocateElem(Linklist L,int *e);//通过位序返回元素值
Status PiorElem(Linklist L,int e);//通过元素来查找前驱
Status NextElem(Linklist L,int e);//通过元素来查找后继
Status ListInsert(Linklist *L,int i,int e);//通过位置插入元素
Status ListDelete(Linklist *L,int i);//删除元素
Status ListTraverse(Linklist L);//遍历输出
Status CreatList(Linklist *L,int n);//输入n个数字
int main()
{
Linklist L;
L=NULL;
title();
//输入选项
int option;
cin>>option;
int ads = 0;
while(option!=0)
{
ads = 0;
switch(option)
{
case 1:
ads=InitList(&L);
break;
case 2:
ads=DestroyList(&L);
if(ads){cout<<"成功销毁单链表"<<endl;}
break;
case 3:
ads=ListLength(L);
if(ads!=-1){cout<<"单链表长度为"<<ads<<endl;}
break;
case 4:
if(L==NULL){
cout<<"单链表不存在!"<<endl;
break;
}
int loc,e;
e=0;
cout<<"请输入元素位置:";
cin>>loc;
ads=GetElement(L,loc,&e);
if(ads==1)
{
cout<<"在位置"<<loc<<"元素值为"<<e<<endl;
}
break;
case 5:
if(L==NULL){
cout<<"单链表不存在!"<<endl;
break;
}
int n;
cout<<"请输入想找的元素";
cin>>n;
ads=LocateElem(L,&n);
break;
case 6:
if(L==NULL){
cout<<"单链表不存在!"<<endl;
break;
}
int num;
cout<<"请输入一个元素:"<<endl;
cin>>num;
ads = PiorElem(L,num);
break;
case 7:
if(L==NULL){
cout<<"单链表不存在!"<<endl;
break;
}
int num1;
cout<<"请输入一个元素:"<<endl;
cin>>num1;
ads = NextElem(L,num1);
break;
case 8:
if(L==NULL){
cout<<"单链表不存在!"<<endl;
break;
}
int num2;
ads = ListLength(L);
cout<<"请输入元素插入的位置:"<<endl;
cin>>num2;
if(num2<1||num2>(ads+1)){
cout<<"请输入元素位置在1-"<<ads+1<<"之间"<<endl;
break;
}
int number;
cout<<"请输入元素的值:"<<endl;
cin>>number;
ads = ListInsert(&L,num2,number);
break;
case 9:
if(L==NULL){
cout<<"单链表不存在!"<<endl;
break;
}
int num3;
ads = ListLength(L);
cout<<"请输入元素删除的位置:"<<endl;
cin>>num3;
if(num3<1||num3>ads){
cout<<"请输入元素位置在1-"<<ads<<"之间"<<endl;
break;
}
ads = ListDelete(&L,num3);
break;
case 10:
ads = ListLength(L);
if(ads == 0){
cout<<"这是一个空表!"<<endl;
break;
}
else if(ads>0){
cout<<"单链表中的元素为:"<<endl;
ListTraverse(L);
cout<<endl;
break;
}
break;
case 11:
if(L==NULL){
cout<<"单链表不存在!"<<endl;
break;
}
int num4;
cout<<"请输入插入的元素个数:"<<endl;
cin>>num4;
if(num4<1){
cout<<"输入插入元素的数目有误!"<<endl;
break;
}
ads = CreatList(&L,num4);
break;
default:
cout<<"输入操作有误,请重新输入:"<<endl;
}
cout<<"输入选项:"<<endl;
cin>>option;
}
return 0;
}
Status InitList(Linklist *L)//二级指针,我对它的理解:malloc函数返回的是一个区域的首地址,而我们的目的就是开辟区域的首地址等于链表的首地址,因而以二级指针传入
{
if(*L!=NULL)
{
cout<<"以存在单链表,请销毁后再初始化!"<<endl;
return ERROR;
}
Linklist p;
p = (Linklist)malloc(LEN);
if(p==NULL)
{
cout<<"申请内存空间失败"<<endl;
return FALSE;
}
p->next=NULL;
*L = p;
cout<<"初始化成功!"<<endl;
return TRUE;
}
Status DestroyList(Linklist *L) //传单链表的首地址
{
Linklist p;
if(*L!=NULL)
{
while(*L)
{
p=*L;
*L=(*L)->next;
free(p);
}
return TRUE;
}
else
{
cout<<"链表不存在"<<endl;
return FALSE;
}
}
Status ListLength(Linklist L)
{
Linklist p;
if(L==NULL){
cout<<"单链表不存在"<<endl;
return ERROR;
}
p=L;
int i=0;
for(i=0;p->next!=NULL;i++)
{
p=p->next;
}
return i;
}
Status GetElement(Linklist L,int i,Elemtype *e)
{
Linklist p;
p = L->next;
int j=1;
while(p&&j<i)
{
p=p->next;
j++;
}
if(!p||j>i)
{
cout<<"请输入正确的位置"<<endl;
return FALSE;
}else
{
*e=p->data;
}
return TRUE;
}
Status LocateElem(Linklist L,int *e)
{
Linklist p;
int result;
result = ListLength(L);
if(result==0){
cout<<"这是一个空表"<<endl;
return FALSE;
}
else if(result==-1){
return FALSE;
}
int loc[100]={0};//在链表中可能会有许多相同的值,以数组形式进行输出
int j=0;
p=L->next;
for(int i=1;p!=NULL;i++)
{
if(p->data==*e)
{
loc[j]=i;
j++;
}
p=p->next;
}
if(loc[0]==0)
{
cout<<"不存在这样元素"<<endl;
return TRUE;
}else
{
cout<<"位次是";
for(int i=0;loc[i+1]!=0;i++)
{
cout<<loc[i]<<endl;
}
cout<<endl;
return TRUE;
}
}
Status PiorElem(Linklist L,int e)
{
int i = 0;
Linklist p,q;
p = L->next;
while(p!=NULL){
if(p->data==e&&i==0){
cout<<"首个元素,没有直接前驱"<<endl;
break;
}
if(p->data==e&&i!=0){
cout<<"单链表中的元素前驱为:"<<(q->data)<<endl;
break;
}
q = p;
p = p->next;
i++;
}
if(p==NULL){
cout<<"该单链表中没有元素!"<<endl;
return FALSE;
}
return TRUE;
}
Status NextElem(Linklist L,int e)
{
Linklist p;
p = L->next;
while(p!=NULL){
if(p->data==e){
if(p->next==NULL){
cout<<"该元素没有直接后继"<<endl;
break;
}
if(p->next!=NULL){
cout<<"单链表中的元素后继为:"<<(p->next->data)<<endl;
break;
}
}
p = p->next;
}
return TRUE;
}
Status ListInsert(Linklist *L,int i,int e)
{
if(*L==NULL){
cout<<"单链表不存在!"<<endl;
return FALSE;
}
int j=1;
Linklist p,s;
s = (Linklist)malloc(LEN);
if(s==NULL){
cout<<"申请内存空间失败!"<<endl;
return ERROR;
}
s->data = e;
p = (*L);
while(j<i&&p!=NULL){
p=p->next;
j++;
}
s->next = p->next;
p->next = s;
cout<<"插入成功!"<<endl;
return TRUE;
}
Status ListDelete(Linklist *L,int i)
{
if(*L==NULL){
cout<<"单链表不存在!"<<endl;
return FALSE;
}
Linklist p,q;
p = (*L);
int j=0;
while(p!=NULL&&j<i){
q = p;
p = p->next;
j++;
}
q->next=p->next;
cout<<"删除的元素是"<<p->data<<endl;
free(p);
cout<<"删除成功"<<endl;
return TRUE;
}
Status ListTraverse(Linklist L)
{
Linklist p;
p = L->next;
while(p!=NULL){
cout<<p->data<<" ";
p = p->next;
}
return TRUE;
}
Status CreatList(Linklist *L,int n)//n 为想要插入元素的个数 头插法
{
if(*L==NULL){
cout<<"单链表不存在!"<<endl;
return FALSE;
}
Linklist p;
int newnum[n];
newnum[n] = {0};
int a = 0;
int j = 0;
cout<<"请输入插入的n个元素:"<<endl;
for(j=0;j<n;j++)
{
cin>>a;
newnum[j]=a;
}
if(j!=n){
cout<<"输入个数小于"<<n<<"个"<<endl;
return FALSE;
}
for(int i=1;i<=n;i++)
{
p = (Linklist)malloc(LEN);
if(!p){
cout<<"申请空间失败!"<<endl;
return ERROR;
}
p->data = newnum[i-1];
p->next = (*L)->next;
(*L)->next = p;
}
cout<<"插入成功!"<<endl;
return TRUE;
}
void title()
{
cout<<"*******************************************"<<endl;
cout<<"******* 1.初始化或重置链表 ********"<<endl;
cout<<"******* 2.销毁链表 ********"<<endl;
cout<<"******* 3.链表中数据元素的个数 ********"<<endl;
cout<<"******* 4.所指位序的元素值 ********"<<endl;
cout<<"******* 5.链表已存在元素的位序 ********"<<endl;
cout<<"******* 6.请输入元素,求直接前驱 ********"<<endl;
cout<<"******* 7.请输入元素,求直接后继 ********"<<endl;
cout<<"******* 8.在第i个位置插入元素 ********"<<endl;
cout<<"******* 9.删除第i个元素 ********"<<endl;
cout<<"******* 10.输出所输入的链表元素 ********"<<endl;
cout<<"******* 11.输入链表元素 ********"<<endl;
cout<<"******* 0.退出 ********"<<endl;
cout<<"*******************************************"<<endl;
}