您的位置:首页 > 编程语言 > C语言/C++

基于C语言的线性表操作,包含单链表和顺序线性表两种类型

2017-09-02 11:59 459 查看
用了四天的闲余时间,终于写完了线性表的顺序和链式两种结构的代码,进度有些慢,因为的确遇到了一些问题,也学到了一些知识,上传代码,同时代码同步更新到我创建的项目里,欢迎指出代码或者算法等等的不足和修改意见!

项目链接:https://code.csdn.net/a894554149/link_based_on_c/tree/master

/*顺序存储结构的线性表操作函数*/
#include<stdio.h>
#include<stdbool.h>
#define MAXSIZE 100
#define OK 0
#define ERROR 1

typedef int Status;
typedef int ElemType;

typedef struct{
ElemType data[MAXSIZE];
int Length;
} SqList;

Status InitList(SqList *L) //初始化一个sq线性表
{
L->Length = 0;
return OK;
}

Status ListInsert(SqList *L,int i,ElemType e)//在线性表L中第i个位置插入新元素e
{
int j;
if( i<1 || i>L->Length+1 )
{
return ERROR;
}

if(L->Length+1 > MAXSIZE)
{
return ERROR;
}
for( j=L->Length; j>i-1 ;j-- )
{
L->data[j] = L->data[j-1];
}

L->data[i-1] = e;
L->Length++;
return OK;
}

bool ListEmpty(SqList L) //判断线性表是否为空表
{
return !(bool)L.Length;
}

void printList(SqList L)//打印顺序线性表
{
int i;
if(L.Length == 0)
{
printf("List is Empty!");
}
printf("\n");
for( i=0; i<L.Length; i++ )
{
printf("%d ",L.data[i]);
}
printf("\n");
printf("\n");
}

Status ClearList(SqList *L) //清空线性表
{
/*int i;
for( i=0; i<L->Length; i++)
{
L->data[i] = 0
} */ //其实这个for循环可以不用写
L->Length = 0;

return OK;
}

Status GetElem(SqList L, int i, ElemType *e) //取线性表L中第i个元素赋值给e
{
if( i<1 || i>L.Length )
{
return ERROR;
}

*e = L.data[i-1];

return OK;
}

Status LocateElem(SqList L, ElemType e) //在线性表L中定位元素e
{
int i;
if(L.Length == 0)
{
return 0;
}
for( i=0; i < L.Length; i++)
{
if(L.data[i] == e)
{
return i+1;
}
}
return 0;
}

Status ListLength(SqList L)
{
return L.Length;
}

Status ListDelete(SqList *L, int i, ElemType *e)
{
int j;
if( i<1 || i>L->Length ) //这里不用判断是否为空表
{ //因为是空表的话,L->Length为0
return ERROR; //小于1或大于0包含了全体实数,所以是空表必然返回ERROR
}

*e = L->data[i-1];

for( j=i-1; j < L->Length-1; j++ )
{
L->data[j] = L->data[j+1];
}

L->Length--;

return OK;
}
/*顺序存储结构的主函数*/
#include</home/linux/ds&a/list/sequence/Sequence.c> //这里需要填写sequence.c文件的绝对路径
#define MAXLIST 10

void main()
{
SqList s[MAXLIST];//注意,不同链表的数据类型不一样
int m = 0; //创建的线性表数目
int n = 0; //选定的线性表
int d = 0; //选定的操作
int i = 0; //线性表中的位置
int e = 0; //线性表中的数据
while(1)
{
printf("1:创建线性表\n");
printf("2:操作线性表\n");
printf("0:退出系统!\n\n");
printf("请输入操作代码:");
while( scanf("%d",&d)== 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}
getchar();
if ( 0 == d ) //0:退出系统
{
break;
}
else if ( 1 == d ) //1:创建线性表
{
if( m >= MAXLIST )
{
printf("\t\t\t已达到最大可创建的线性表数目,创建失败!\n");
continue;
}
InitList( &s[m] );
printf("\t\t\t编号为%d的线性表已被创建!\n",m+1);
m++;
}
else if( 2 == d ) //2:操作线性表
{
if( m == 0)
{
printf("\t\t\t还没有线性表被创建,请先创建线性表!\n");
continue;
}

printf("\n请输入要操作的线性表代码,返回主菜单,请输入0:");
while(scanf("%d",&n) == 0)
{
getchar();
printf("输入格式错误,请重新输入,返回主菜单,请输入0:");
}
getchar();
if( n == 0 )
{
printf("\n\n");
continue;
}
else if (n > m)
{
printf("\n\t\t\t还没有那个线性表,请先创建!\n\n");
}
while(d != 0)
{
printf("\n\t\t\t当前选定线性表的编号为%d\n",n);
printf("1:插入元素\n");
printf("2:删除元素\n");
printf("3:是否为空\n");
printf("4:获取元素\n");
printf("5:定位元素\n");
printf("6:打印线性表\n");
printf("7:清空线性表\n");
printf("8:获取线性表元素个数\n");
printf("请输入要进行什么操作,返回主菜单,请输入0:");
while(scanf("%d",&d) == 0)
{
getchar();
printf("输入格式错误,请重新输入,返回主菜单,请输入0:");
}
getchar();
if( d == 0 )
{
printf("\n\n");
continue;
}
else if( 1 == d )
{
while(1)
{
printf("请输入要插入的位置,结束插入请输入0:");
while( scanf("%d",&i) == 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}
getchar();
if(i == 0)
{
break;
}
printf("请输入要插入的元素:");
while( scanf("%d",&e) == 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}

if(ListInsert(&s
, i, e) == ERROR)
{
printf("\n\t\t\t插入失败,没有那个位置!\n\n");
}
else
{
printf("\n\t\t插入成功,已将元素%d插入线性表%d的第%d个位置\n\n",e,n,i);
}

}
}
else if( 2 == d )
{
while(1)
{
printf("请输入要删除的位置,结束插入请输入0:");
while( scanf("%d",&i) == 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}
getchar();
if(i == 0)
{
break;
}

if(ListDelete(&s
, i, &e) == ERROR)
{
printf("\n\t\t\t删除失败,没有那个位置!\n\n");
}
else
{
printf("\n\t\t删除成功,已将元素%d从线性表%d的第%d个位置删除\n\n",e,n,i);
}
}

}
else if( 3 == d )
{
printf("\n\t\t\t这个线性表%s空的。\n\n",ListEmpty(s
)? "是":"不是" );
}
else if( 4 == d )
{
printf("请输入要获取元素的位置,结束获取请输入0:");
while( scanf("%d",&i) == 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}
if(i != 0)
{
if(GetElem(s
, i, &e) == ERROR)
{
printf("\n\t\t\t获取失败,没有那个位置!\n\n");
}
else
printf("\n\t\t\t获取成功,数据为%d\n",e);
}
}
else if( 5 == d )
{
printf("请输入要查找的元素:");
while( scanf("%d",&e) == 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}
if( LocateElem(s
,e) == 0)
{
printf("\n\t\t\t查找完毕,线性表中没有这个数据!\n");
}
else
printf("\n\t\t\t查找完毕,该数据在线性表中第%d个位置\n",LocateElem(s
,e));
}
else if( 6 == d )
{
printList(s
);
}
else if( 7 == d )
{
ClearList(&s
);
printf("\n\t\t\t线性表已清空!\n");
}
else if( 8 == d )
{
printf("\n\t\t\t该线性表的长度为%d\n",ListLength(s
));
}
else
{
printf("\n\t\t\t没有那个操作!\n");
}
}
}
else
{
printf("\n\t\t\t没有那个操作!\n");
continue;
}

}
/*SqList sql;
int e;
InitList( &sql );
printf("The List is Empty? %d\n",
4000
ListEmpty(sql));
ListInsert(&sql, 1, 6);
ListInsert(&sql, 1, 6);
ListInsert(&sql, 1, 8);
ListInsert(&sql, 1, 6);
ListInsert(&sql, 1, 8);
ListInsert(&sql, 1, 6);
ListInsert(&sql, 1, 8);
ListInsert(&sql, 6, 9);
printf("The List is Empty? %d\n",ListEmpty(sql));
printList(sql);
GetElem(sql, 3, &e);
printf("the NO.3 data in List is %d\n",e);
printf("%d\n",LocateElem(sql,9));
ListDelete(&sql, 6, &e);
printf("No.6 data %d has been deleted!\n",e);
printf("%d\n",ListLength(sql));*/
}

/*链式存储结构的操作函数*/
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

#define ERROR 1
#define OK 0
typedef int ElemType;
typedef int Status;

typedef struct Node //结点的结构体
{
ElemType data; //数据
struct Node *next;
} Node;

typedef struct Node* LinkList; //定义LinkList为指向节点结构体的指针类型的别名
//即LinkList*定义的是指向一个结点指针的指针,即头指针

/*void main()
{
int e;
LinkList l;
InitList( &l);
printf("Length = %d\n",ListLength(l));
printf("%p\n",l->next);
printf("The LinkList %s Empty\n",ListEmpty(l)? "is":"is not");
ListInsert(&l, 1, 11);
ListInsert(&l, 1, 36);
ListInsert(&l, 1, 59);
ListInsert(&l, 1, 33);
ListInsert(&l, 1, 12);
printf("Length = %d\n",ListLength(l));
printf("The LinkList %s Empty\n",ListEmpty(l)? "is":"is not");
PrintfList(l);
GetElem(l, 2, &e);
printf("%d\n",e);
ListDelete(&l, 1, &e);
printf("%d\n",e);
PrintfList(l);
printf("Length = %d\n",ListLength(l));
printf("The LinkList %s Empty\n",ListEmpty(l)? "is":"is not");
ListClear( &l );
PrintfList(l);
printf("The LinkList %s Empty\n",ListEmpty(l)? "is":"is not");
ListInsert(&l, 1, 11);
ListInsert(&l, 1, 36);
ListInsert(&l, 1, 59);
ListInsert(&l, 1, 33);
ListInsert(&l, 1, 12);
PrintfList(l);
e = LocateElem(l, 36);
printf("Locate = %d\n",e);
}*/

Status InitList(LinkList *L) //注意这里L是一个二级指针
{
(*L) = (LinkList) malloc(sizeof(Node)); //为了操作的方便性,创建一个头结点
(*L)->data = 0; //头结点的数据内存放链表的长度
(*L)->next = NULL;//头结点指针指向空
}

Status ListLength(LinkList L) //获取单链表的长度
{
return L->data;
}

Status ListEmpty(LinkList L)
{
if( L->data == 0)
{
return 1;
}
else
{
return 0;
}

//return L->data? 0:1; //上述代码也可以写成这样
}

Status ListInsert(LinkList *L, int i, ElemType e) //插入函数,在单链表(**L)中的第i个位置插入元素e
{
int j;
LinkList p,t;
/*if( *L == NULL && i != 1 ) //链表为空,且不在第一个位置插入,返回ERROR
{
return ERROR;
}*/ //在for循环里的判断语句保证了插入位置的准确性

p = *L; //将头结点的地址赋值给p,即现在p内存放的是头结点的地址

for( j=1; j<i; j++ ) //查找,从第一个元素,查找到第i-1个元素
{
if( (p->next) == NULL && (j < i-1) ) // 如果查找的当前元素next为NULL,而且当前元素还不是i-1,说明无法在第i个位置插入元素
{
return ERROR;
}
p = p->next;
}  //结束循环后,p内存放的是第i-1个元素的地址,即p->next存放的是i的地址
t = (LinkList)malloc(sizeof(Node)); //开辟一个新的空间,存放新的结点,并将结点的地址赋值t
t->data = e; //将e赋值给t的数据
t->next = p->next; //将t的next指向以前的第i个元素,如果插入的位置为表尾,则这里被赋值为NULL
p->next = t; //将p的next指向t
(*L)->data++; //头结点的数据自加1,这里是代表的链表长度,所以每次插入新元素都要自加1
}

Status ListDelete(LinkList *L, int i,ElemType *e)//在单链表L中删除第i个元素,并用e返回其值
{
int j;
LinkList t,p;
p = *L;
if( i<1 || i>(*L)->data ) //判断i是否在合法的区间,不在的话返回ERROR
{
return ERROR;
}

for( j=1; j < i; j++ )
{
p = p->next;
}// 循环结束后,(*L)指向第i-1个结点

t = p->next;
*e = t->data;
p->next = p->next->next;
free(t);

(*L)->data--;
}

Status printList(LinkList L) //打印单链表L
{
if(L->next == NULL)
{
printf("PRINT ERROR:The List is empty!\n");
return ERROR;
}
L = L->next; //跳过头结点
while( L->next != NULL ) //循环打印单链表,但无法打印最后一个结点的数据
{
printf("%d ",L->data);
L = L->next;
}
printf("%d\n",L->data); //打印最后一个结点的数据并换行
}

Status GetElem(LinkList L,int i, ElemType *e) //在线性表L中取得第i个位置的元素,并用e返回其值
{
int j;

if ( i<1 || i>L->data )//判断i是否在合法的区间,不在的话,返回ERROR
{
return ERROR;
}

for( j=1; j <= i; j++) //这里因为j<=i,所以会跳过头结点
{
L = L->next;
}

*e =  L->data;

return OK;
}

ClearList(LinkList *L)
{
LinkList t,p;
p = *L;
p = p->next; //跳过头结点
while( (*L)->data != 0 )
{
t = p;
p = p->next;
free(t);
(*L)->data--;
}

(*L)->next = NULL;

return OK;
}

LocateElem(LinkList L,ElemType e)
{
int j = (int) L->data;
int i = 1;
if(L->next == NULL)
{
return ERROR;
}
L = L->next;
while(j--)
{
if(L->data == e)
{
return i;
}
L = L->next;
i++;
}

return 0;
}


/*链式存储结构的主函数*/
#include</../link.c> //这里需要填写link.c文件的绝对路径
#define MAXLIST 10

void main()
{
LinkList s[MAXLIST];//注意,不同链表的数据类型不一样
int m = 0; //创建的线性表数目
int n = 0; //选定的线性表
int d = 0; //选定的操作
int i = 0; //线性表中的位置
int e = 0; //线性表中的数据
while(1)
{
printf("1:创建线性表\n");
printf("2:操作线性表\n");
printf("0:退出系统!\n\n");
printf("请输入操作代码:");
while( scanf("%d",&d)== 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}
getchar();
if ( 0 == d ) //0:退出系统
{
break;
}
else if ( 1 == d ) //1:创建线性表
{
if( m >= MAXLIST )
{
printf("\t\t\t已达到最大可创建的线性表数目,创建失败!\n");
continue;
}
InitList( &s[m] );
printf("\t\t\t编号为%d的线性表已被创建!\n",m+1);
m++;
}
else if( 2 == d ) //2:操作线性表
{
if( m == 0)
{
printf("\t\t\t还没有线性表被创建,请先创建线性表!\n");
continue;
}

printf("\n请输入要操作的线性表代码,返回主菜单,请输入0:");
while(scanf("%d",&n) == 0)
{
getchar();
printf("输入格式错误,请重新输入,返回主菜单,请输入0:");
}
getchar();
if( n == 0 )
{
printf("\n\n");
continue;
}
else if (n > m)
{
printf("\n\t\t\t还没有那个线性表,请先创建!\n\n");
}
while(d != 0)
{
printf("\n\t\t\t当前选定线性表的编号为%d\n",n);
printf("1:插入元素\n");
printf("2:删除元素\n");
printf("3:是否为空\n");
printf("4:获取元素\n");
printf("5:定位元素\n");
printf("6:打印线性表\n");
printf("7:清空线性表\n");
printf("8:获取线性表元素个数\n");
printf("请输入要进行什么操作,返回主菜单,请输入0:");
while(scanf("%d",&d) == 0)
{
getchar();
printf("输入格式错误,请重新输入,返回主菜单,请输入0:");
}
getchar();
if( d == 0 )
{
printf("\n\n");
continue;
}
else if( 1 == d )
{
while(1)
{
printf("请输入要插入的位置,结束插入请输入0:");
while( scanf("%d",&i) == 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}
getchar();
if(i == 0)
{
break;
}
printf("请输入要插入的元素:");
while( scanf("%d",&e) == 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}

if(ListInsert(&s
, i, e) == ERROR)
{
printf("\n\t\t\t插入失败,没有那个位置!\n\n");
}
else
{
printf("\n\t\t插入成功,已将元素%d插入线性表%d的第%d个位置\n\n",e,n,i);
}

}
}
else if( 2 == d )
{
while(1)
{
printf("请输入要删除的位置,结束插入请输入0:");
while( scanf("%d",&i) == 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}
getchar();
if(i == 0)
{
break;
}

if(ListDelete(&s
, i, &e) == ERROR)
{
printf("\n\t\t\t删除失败,没有那个位置!\n\n");
}
else
{
printf("\n\t\t删除成功,已将元素%d从线性表%d的第%d个位置删除\n\n",e,n,i);
}
}

}
else if( 3 == d )
{
printf("\n\t\t\t这个线性表%s空的。\n\n",ListEmpty(s
)? "是":"不是" );
}
else if( 4 == d )
{
printf("请输入要获取元素的位置,结束获取请输入0:");
while( scanf("%d",&i) == 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}
if(i != 0)
{
if(GetElem(s
, i, &e) == ERROR)
{
printf("\n\t\t\t获取失败,没有那个位置!\n\n");
}
else
printf("\n\t\t\t获取成功,数据为%d\n",e);
}
}
else if( 5 == d )
{
printf("请输入要查找的元素:");
while( scanf("%d",&e) == 0 )
{
getchar();
printf("输入格式错误,请重新输入:");
}
if( LocateElem(s
,e) == 0)
{
printf("\n\t\t\t查找完毕,线性表中没有这个数据!\n");
}
else
printf("\n\t\t\t查找完毕,该数据在线性表中第%d个位置\n",LocateElem(s
,e));
}
else if( 6 == d )
{
printList(s
);
}
else if( 7 == d )
{
ClearList(&s
);
printf("\n\t\t\t线性表已清空!\n");
}
else if( 8 == d )
{
printf("\n\t\t\t该线性表的长度为%d\n",ListLength(s
));
}
else
{
printf("\n\t\t\t没有那个操作!\n");
}
}
}
else
{
printf("\n\t\t\t没有那个操作!\n");
continue;
}

}
/*SqList sql;
int e;
InitList( &sql );
printf("The List is Empty? %d\n",ListEmpty(sql));
ListInsert(&sql, 1, 6);
ListInsert(&sql, 1, 6);
ListInsert(&sql, 1, 8);
ListInsert(&sql, 1, 6);
ListInsert(&sql, 1, 8);
ListInsert(&sql, 1, 6);
ListInsert(&sql, 1, 8);
ListInsert(&sql, 6, 9);
printf("The List is Empty? %d\n",ListEmpty(sql));
printList(sql);
GetElem(sql, 3, &e);
printf("the NO.3 data in List is %d\n",e);
printf("%d\n",LocateElem(sql,9));
ListDelete(&sql, 6, &e);
printf("No.6 data %d has been deleted!\n",e);
printf("%d\n",ListLength(sql));*/
}

其实大家可以发现,这两种存储结构的主函数没有很大的区别,只是在一开始的数据类型定义上有小小的区别,这也是C语言函数化的好处。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息