数据结构C语言—线性表【顺序存储——链式用法】静态单链表(定义结构体数组模拟链表实现)【2021-07-02】

数据结构C语言—线性表【顺序存储——链式用法】静态单链表(定义结构体数组模拟链表实现)

SingleLinkListStatic.h

#define MAXSIZE 1000
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE 1
#define OVERFLOW 1
#define NULLNODE -1
#define SLHead 0

typedef int Status;
typedef int DataType;
typedef int NextDataPoint;
typedef int Point;
typedef int *Pt;

typedef struct
{
	DataType data;//该节点的数据域,其中头节点里存放该链表元素个数,即顺序表长度 
	NextDataPoint cur;//指向下一个结点的指针 
}SLNode,SLinkList[MAXSIZE];//默认带头节点,即数组0位置为头节点 

void Init_SLinkList(SLinkList S);//初始化一个空的线性表S
void Head_Init_SLinkList(SLinkList S);//初始化一个空的线性表S
void Tail_Init_SLinkList(SLinkList S);//初始化一个空的线性表S
//Status DestoryList(int* L);//销毁线性表S
void ClearList(SLinkList S);//清空线性表S

Status IsEmptySLinkList(SLinkList S);//若S为空表,则返回TRUE,否则返回FALSE
DataType SLinkListLength(SLinkList S);//返回S中数据元素个数
DataType GetElem(SLinkList S,DataType i,Pt e);//用e返回S中第i个元素的值,操作成功返回OK,否则返回ERROR
DataType LocateElem(SLinkList S,DataType e);//返回e在S中的位置,有该数据元素则返回其位置,否则返回0

Status PriorElem(SLinkList S,DataType e,Pt proe);//若若e是S的数据元素,且不是第一个,则用proe返回它的前驱。操作成功返回OK,否则返回-6699
Status NextElem(SLinkList S,DataType e,Pt nexte);//若e是S的数据元素,且不是最后一个,则用nexte返回它的后继。操作成功返回OK,否则返回-6699
Status SLinkListInsert(SLinkList S,DataType i,DataType e);//在S第i个位置之前插入新的元素e,S长度加1,成功操作返回OK,否则返回ERROR
DataType SLinkListDelete(SLinkList S,DataType i,Pt e);//删除S的第i个数据元素,并用e返回其值,S长度减1,操作成功返回删除的值,否则返回ERROR

Status SLinkListTraverse(SLinkList S);//依次对S每个数据元素调用函数,成功遍历返回OK,否则返回ERROR

SingleLinkListStatic.c

#include "SingleLinkListStatic.h"
#include <stdio.h>
void Init_SLinkList(SLinkList S)//初始化一个空的线性表S
{
	
	DataType i;
	puts("==开始初始化静态单链表S!==");
	for(S[0].data=0,i=0;i<MAXSIZE;i++)//头节点在0位置,它的数据域data是整个链表元素的个数,即顺序表长,表长初始化为0
	{
		S[i].cur=NULLNODE;//NULLNODE代表空指针
	}
	puts("==静态单链表S初始化完成!==");
}
void Head_Init_SLinkList(SLinkList S)//头插法建立静态单链表S
{
	DataType i,n,k,co;
	Point p=SLHead;//定义一个p指向头节点
	fflush(stdin);
	printf("\n开始头插法(以f结束):");
	for(i=0;i+1<MAXSIZE;i++)
	{
		k=scanf("%d",&n);
		if(k==0)
		{
			break;
		}
		else
		{
			co++;
			S[i+1].data=n;
			S[i+1].cur=S[p].cur;
			S[p].cur=i+1;
			S[0].data++;
		}
	}
	fflush(stdin);
}
void Tail_Init_SLinkList(SLinkList S)//尾插法建立静态单链表S
{
	DataType i,n,k,co;
	Point p=SLHead;//定义一个p指向头节点 
	fflush(stdin);
	printf("\n开始尾插法(以f结束):");
	for(i=0;i+1<MAXSIZE;i++)
	{
		k=scanf("%d",&n);
		//printf("k=%d,n=%d\n",k,n); 
		if(k==0)
		{
			break;
		}
		else
		{
			co++;
			S[i+1].data=n;
			S[i+1].cur=S[p].cur;
			S[p].cur=i+1;
			p=i+1;
			S[0].data++;
		}
	}
	fflush(stdin);
}
//Status DestoryList(int* L);//销毁线性表S
void ClearList(SLinkList S)//清空线性表S
{
	DataType i;
	puts("\n==开始清空静态单链表S!==");
	for(S[0].data=0,i=0;i<MAXSIZE;i++)//头节点在0位置,它的数据域data是整个链表元素的个数,即顺序表长,表长初始化为0
	{
		S[i].cur=NULLNODE;//NULLNODE代表空指针
	}
	puts("==清空静态单链表S完成!==");
}

Status IsEmptySLinkList(SLinkList S)//若S为空表,则返回TRUE,否则返回FALSE
{
	if(S[0].data==0)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}
DataType SLinkListLength(SLinkList S)//返回S中数据元素个数
{
	//printf("\nS中当前元素个数是:%d\n",S[0].data);
	return S[0].data; 
}
DataType GetElem(SLinkList S,DataType i,Pt e)//用e返回S中第i个元素的值,操作成功返回OK,否则返回ERROR
{
	if(IsEmptySLinkList(S)==TRUE)
	{
		printf("\n当前表空,不能查询!\n",i);
		return ERROR;
	}
	if(i>SLinkListLength(S)||i<1) 
	{
		printf("\n当前查询位置%d不合法!\n",i);
		return ERROR;
	}
	int p=S[0].cur,co=0;
	while(p!=-1)
	{
		co++;
		if(co==i)
		{
			*e=S[p].data;
			return OK;
		}
		p=S[p].cur;
	}
}
DataType LocateElem(SLinkList S,DataType e)//返回e在S中的位置,有该数据元素则返回其位置,否则返回0
{
	if(IsEmptySLinkList(S)==TRUE)
	{
		return ERROR;
	}
	int p=S[0].cur,co=0;
	while(p!=-1)
	{
		co++;
		if(S[p].data==e)
		{
			return co;
		}
		p=S[p].cur;
	}
	return ERROR;
}
Status PriorElem(SLinkList S,DataType e,Pt proe)//若若e是S的数据元素,且不是第一个,则用proe返回它的前驱。操作成功返回OK,否则返回-6699
{
	if(IsEmptySLinkList(S)==TRUE)
	{
		*proe=-6699; 
		printf("\n当前表S空,不能查询%d的前驱值!\n",e);
		return ERROR;
	}
	if(IsEmptySLinkList(S)!=TRUE&&LocateElem(S,e)==ERROR)
	{
		*proe=-6699; 
		printf("\n值%d不在表S中,无法返回其前驱值!\n",e);
		return ERROR;
	}
	if(LocateElem(S,e)==1)
	{
		*proe=-6699; 
		printf("值%d是表S第一个元素,无前驱值!\n",e);
		return ERROR;
	}
	int p=S[0].cur,co=0;
	while(p!=-1)
	{
		co++;
		if(co==LocateElem(S,e)-1)
		{
			*proe=S[p].data;
			return OK;
		}
		p=S[p].cur;
	}
}
Status NextElem(SLinkList S,DataType e,Pt nexte)//若e是S的数据元素,且不是最后一个,则用nexte返回它的后继。操作成功返回OK,否则返回-6699
{
	if(IsEmptySLinkList(S)==TRUE)
	{
		*nexte=-6699;
		printf("\n当前表S空,不能查询%d的后继值!\n",e);
		return ERROR;
	}
	if(IsEmptySLinkList(S)!=TRUE&&LocateElem(S,e)==ERROR)
	{
		*nexte=-6699;
		printf("\n值%d不在表S中,无法返回其后继值!\n",e);
		return ERROR;
	}
	if(LocateElem(S,e)==S[0].data)
	{
		*nexte=-6699;
		printf("值%d是表S最后一个元素,无后继值!\n",e);
		return ERROR;
	}
	int p=S[0].cur,co=0;
	while(p!=-1)
	{
		co++;
		if(co==LocateElem(S,e)+1)
		{
			*nexte=S[p].data;
			return OK;
		}
		p=S[p].cur;
	}
}
Status SLinkListInsert(SLinkList S,DataType i,DataType e)//在S第i个位置之前插入新的元素e,S长度加1,成功操作返回OK,否则返回ERROR
{

	if(SLinkListLength(S)==MAXSIZE) 
	{
		printf("\n当前表S已满,不能再插入!\n");
		return ERROR;
	}
	if(i>SLinkListLength(S)+1||i<1)
	{
		printf("\n插入位置%d不合法,不能再插入!\n",i);
		return ERROR;
	}
	int p=SLHead,q,co=-1; 
/*方法一: 容易产生假溢出,但是分配空间时代码简单,容易想到 
	q=S[0].data+1;//给待插入的元素e分配一个位置 
	S[q].data=e; //将e放入分配的位置
*/
/*方法二: 不会产生假溢出现象,充分利用每个数组位置
	int j,f=0;
	for(int j=1;j<MAXSIZE;j++)
	{
		if(S[j].cur==NULLNODE)
		{
			while(p!=-1)
			{
				if(S[p].cur==-1)
				{
					break;
				}
				p=S[p].cur;
			}//找到尾结点的指针值,即数组下标 
//			printf("尾结点数组下标是:%d\n",p); 
			if(p==j)
			{
				continue;
			}
			else
			{
				q=j;
				S[q].data=e;//不是则用作分配新空间  
//				printf("新分配的空间是数组的%d位置!\n",q);
				break; 
			}
		}
	}
*/ 
	int j,f=0;
	for(int j=1;j<MAXSIZE;j++)
	{
		if(S[j].cur==NULLNODE)
		{
			while(p!=-1)
			{
				if(S[p].cur==-1)
				{
					break;
				}
				p=S[p].cur;
			}//找到尾结点的指针值,即数组下标 
//			printf("尾结点数组下标是:%d\n",p); 
			if(p==j)
			{
				continue;
			}
			else
			{
				q=j;
				S[q].data=e;//不是则用作分配新空间  
//				printf("新分配的空间是数组的%d位置!\n",q);
				break; 
			}
		}
	}

	p=SLHead;
	while(p!=-1)
	{
		co++;
		if(co==i-1)
		{
			S[q].cur=S[p].cur;
			S[p].cur=q; 
			S[0].data++;
			return OK;
		}
		p=S[p].cur;
	}
}
DataType SLinkListDelete(SLinkList S,DataType i,Pt e)//删除S的第i个数据元素,并用e返回其值,S长度减1,操作成功返回删除的值,否则返回ERROR
{
	if(SLinkListLength(S)==0) 
	{
		printf("\n当前表S空,不能删除任何值!\n");
		return ERROR;
	}
	if(i>SLinkListLength(S)||i<1)
	{
		printf("\n删除位置%d不合法,不能删除任何值!\n",i);
		return ERROR;
	}
	int p=SLHead,co=-1; 
	int q=0;//q用来保存i之前位置的指针 
	while(p!=-1)
	{
		co++;
		if(co==i-1)
		{
			q=p;
//			printf("i之前的是%d=%d,co=%d\n",q,S[q].data,co);
		}
		if(co==i) 
		{	
//		    printf("%d %d是%d,指向%d",p,i,S[p].data,S[p].cur);
			*e=S[p].data;
			S[q].cur=S[p].cur;
			S[p].cur=NULLNODE;
			S[0].data--;
			return OK;
		}
		p=S[p].cur;
	}
}
Status SLinkListTraverse(SLinkList S)//依次对LS每个数据元素调用函数,成功遍历返回OK,否则返回ERROR
{
	int p=S[0].cur;
	if(p==-1)
	{
		printf("【遍历检查】|长度:%d|头结点-->NULL\n",S[0].data);
	}
	else
	{
		printf("\n【遍历检查】|长度:%d|头结点",S[0].data);
		while(p!=-1)
		{
	
			//printf("--->S[%d].data=%d,S[%d].cur=%d",p,S[p].data,p,S[p].cur);
			printf("--->%d",S[p].data);
			p=S[p].cur;
		}
		printf("-->NULL\n"); 
	}
	return OK;
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include "SingleLinkListStatic.h"
/* 线性表——链式表(静态单链表)【自编代码】 */
int main() 
{
	SLinkList S;
	DataType i,e,proe,nexte,n;
	Init_SLinkList(S);
	SLinkListTraverse(S);
	printf("S中当前元素个数是:%d",SLinkListLength(S));
	if(IsEmptySLinkList(S))
	{
		printf("\n======S是空表!======\n");
	}
	else
	{
		printf("\n======S不是空表!======\n");
	}
	
	Tail_Init_SLinkList(S);
	SLinkListTraverse(S);
	printf("S中当前元素个数是:%d\n",SLinkListLength(S));
	if(IsEmptySLinkList(S))
	{
		printf("\n======S是空表!======\n");
	}
	else
	{
		printf("\n======S不是空表!======\n");
	}
	
	printf("请输入要查询的位置:");
	scanf("%d",&i); 
	if(GetElem(S,i,&e))
	{
		printf("S表中%d位置值是:%d\n",i,e);
	}
	printf("请输入要查询位置的值:");
	scanf("%d",&n); 
	if(LocateElem(S,n)!=ERROR)
	{
		printf("\nS表中值%d所在位置是:%d\n",n,LocateElem(S,n));
	}
	else
	{
		if(IsEmptySLinkList(S)==TRUE)
		{
			printf("\n当前表空,不能查询%d的位置!\n",n);
		}
		else
		{
			printf("\n值%d的不在表中,可以加入表中!\n",n);
		}
	}
	printf("请输入要返回其前驱的元素值:");
	scanf("%d",&e); 
	if(PriorElem(S,e,&proe)!=ERROR)
	{
		printf("值%d的前驱值是:%d\n",e,proe);	
	} 
	printf("请输入要返回其后继的元素值:");
	scanf("%d",&e); 
	if(NextElem(S,e,&nexte)!=ERROR)
	{
		printf("值%d的后继值是:%d\n",e,nexte);	
	} 
	printf("请输入要插入的位置和值:");
	scanf("%d %d",&i,&e); 
	SLinkListInsert(S,i,e);
	SLinkListTraverse(S);
	fflush(stdin);
	printf("请输入要删除的位置:");
	scanf("%d",&i); 
	SLinkListDelete(S,i,&e); 
	SLinkListTraverse(S);
	ClearList(S);
	SLinkListTraverse(S);
	printf("S中当前元素个数是:%d",SLinkListLength(S));
	if(IsEmptySLinkList(S))
	{
		printf("\n======S是空表!======\n");
	}
	else
	{
		printf("\n======S不是空表!======\n");
	}

	Head_Init_SLinkList(S);
	SLinkListTraverse(S);
	printf("S中当前元素个数是:%d",SLinkListLength(S));
	if(IsEmptySLinkList(S))
	{
		printf("\n======S是空表!======\n");
	}
	else
	{
		printf("\n======S不是空表!======\n");
	}
	printf("请输入要查询的位置:");
	scanf("%d",&i); 
	if(GetElem(S,i,&e))
	{
		printf("S表中%d位置值是:%d\n",i,e);
	}
	
	printf("请输入要查询位置的值:");
	scanf("%d",&n); 
	if(LocateElem(S,n)!=ERROR)
	{
		printf("\nS表中值%d所在位置是:%d\n",n,LocateElem(S,n));
	}
	else
	{
		if(IsEmptySLinkList(S)==TRUE)
		{
			printf("\n当前表空,不能查询%d的位置!\n",n);
		}
		else
		{
			printf("\n值%d的不在表中,可以加入表中!\n",n);
		}
	}
	printf("请输入要返回其前驱的元素值:");
	scanf("%d",&e); 
	if(PriorElem(S,e,&proe)!=ERROR)
	{
		printf("值%d的前驱值是:%d\n",e,proe);	
	}
	printf("请输入要返回其后继的元素值:");
	scanf("%d",&e); 
	if(NextElem(S,e,&nexte)!=ERROR)
	{
		printf("值%d的后继值是:%d\n",e,nexte);	
	} 
	printf("请输入要插入的位置和值:");
	scanf("%d %d",&i,&e); 
	SLinkListInsert(S,i,e);
	SLinkListTraverse(S);
	fflush(stdin);
	printf("请输入要删除的位置:");
	scanf("%d",&i); 
	SLinkListDelete(S,i,&e);
	SLinkListTraverse(S);
	ClearList(S);
	SLinkListTraverse(S);
	printf("S中当前元素个数是:%d",SLinkListLength(S));
	if(IsEmptySLinkList(S))
	{
		printf("\n======S是空表!======\n");
	}
	else
	{
		printf("\n======S不是空表!======\n");
	}

	system("pause");
	return 0;
}

运行结果示例

在这里插入图片描述


------------------------------------------------------第三次发文章有点激动啊!-----------------------------------------------------
-----------------------------------------------------【数据结构代码自编练习】------------------------------------------------------
----------------------------------------------------------------【TDTX】-----------------------------------------------------------------

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值