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

博主花费四天时间完成了线性表的C语言实现,包括单链表和顺序线性表。代码已上传并同步到个人项目中,欢迎查看并提出建议。尽管两种结构的主函数差异不大,但数据类型定义上有所不同,体现了C语言的函数化优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


项目链接:https://code.youkuaiyun.com/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[n], 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[n], 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[n])? "是":"不是" );
				}
				else if( 4 == d )
				{	
					printf("请输入要获取元素的位置,结束获取请输入0:");
					while( scanf("%d",&i) == 0 )
					{
						getchar();
						printf("输入格式错误,请重新输入:");
					}
					if(i != 0)
					{
						if(GetElem(s[n], 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[n],e) == 0)
					{
						printf("\n\t\t\t查找完毕,线性表中没有这个数据!\n");
					}
					else
						printf("\n\t\t\t查找完毕,该数据在线性表中第%d个位置\n",LocateElem(s[n],e));
				}
				else if( 6 == d )
				{
					printList(s[n]);
				}
				else if( 7 == d )
				{
					ClearList(&s[n]);
					printf("\n\t\t\t线性表已清空!\n");
				}
				else if( 8 == d )
				{
					printf("\n\t\t\t该线性表的长度为%d\n",ListLength(s[n]));
				}
				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));*/
}

/*链式存储结构的操作函数*/
#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[n], 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[n], 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[n])? "是":"不是" );
				}
				else if( 4 == d )
				{	
					printf("请输入要获取元素的位置,结束获取请输入0:");
					while( scanf("%d",&i) == 0 )
					{
						getchar();
						printf("输入格式错误,请重新输入:");
					}
					if(i != 0)
					{
						if(GetElem(s[n], 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[n],e) == 0)
					{
						printf("\n\t\t\t查找完毕,线性表中没有这个数据!\n");
					}
					else
						printf("\n\t\t\t查找完毕,该数据在线性表中第%d个位置\n",LocateElem(s[n],e));
				}
				else if( 6 == d )
				{
					printList(s[n]);
				}
				else if( 7 == d )
				{
					ClearList(&s[n]);
					printf("\n\t\t\t线性表已清空!\n");
				}
				else if( 8 == d )
				{
					printf("\n\t\t\t该线性表的长度为%d\n",ListLength(s[n]));
				}
				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语言函数化的好处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值