《数据结构》(C语言版)——线性表的静态单链表存储结构

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//用到的库文件
#include <stdio.h>  //printf();scanf()
#include <stdlib.h> //exit()
#include <malloc.h> //malloc()
#include <time.h>   //srand((unsigned)time(NULL));
//函数结果状态代码
#define TRUE    1
#define FALSE   0
#define OK      1
#define ERROR   0
#define INFEASIBLE  -1
#define OVERFLOW    -2
//Status是函数的类型,其值是函数结果状态代码
typedef int Status;
//#define ElemType int  //也可以用宏定义确定ElemType类型
typedef char ElemType;
//-----线性表的静态单链表存储结构-----
#define MAXSIZE 10                  //链表的最大长度
typedef struct  LNode {             //自定义数据类型
	ElemType data;                  //数据域
	int cur;                        //游标(指示器cur)
} component, SLinkList[MAXSIZE];
/*
	space[0]作为 备用链表 的头结点,其游标指向空闲备用链表的第一个结点
	space[1]作为 静态链表 的头结点,其游标指向静态单链表的第一个元素
*/

// 操作结果:构造一个空的静态链表。
void InitSpace_SL(SLinkList space) {
	// 将一维数组space中各分量链成一个备用链表,space[0].cur为头指针,“0”表示空指针
	for(int i=0; i<MAXSIZE-1; ++i)
		space[i].cur = i + 1;
	space[MAXSIZE - 1].cur = 0;     // 链表最后一个结点的游标值为0
}// InitSpace_SL 算法2.14

// 获取备用空闲链表对应结构体数组的下标
int Malloc_SL(SLinkList space) {
	// 若备用空闲链表非空,则返回分配的结点下标,否则返回0
	int i = space[0].cur;			// i 指示 备用链表中第一个空闲结点 在结构体数组中的下标
	if(space[0].cur)
		space[0].cur = space[i].cur;// 第0分量的游标指向 空闲备用链表的第一个结点
	return i;
}// Malloc_SL 算法2.15

// 释放分配空间
void Free_SL(SLinkList space, int k) {
	// 将下标为 k 的空闲结点回收到备用链表
	space[k].cur = space[0].cur;
	space[0].cur = k;
}// Free_SL 算法2.16

void difference(SLinkList space, int &S) {
	// 依次输入集合A和B的元素,在一维数组space中建立表示集合(A-B)U(B-A)
	// 的静态链表,S为其头指针。假设备用空间足够大,space[0].cur为其头指针。
	InitSpace_SL(space);            // 初始化备用空间
	S = Malloc_SL(space);           // 生成S的头结点
	int r = S;                      // r指向S的当前最后结点
	int m, n, i, j;
	printf("输入集合A和B的元素个数:\n"); 
	scanf("%d %d", &m, &n);         // 输入A和B的元素个数
	fflush(stdin);					// 清空缓冲区
	for(j=1; j<=m; ++j) {           // 建立集合A的链表
		i = Malloc_SL(space);       // 分配结点
		printf("输入集合A的第%d个元素:\n", j);  
		scanf("%c", &space[i].data);// 输入A的元素。
		fflush(stdin);				// 清空缓冲区
		space[r].cur = i;           // 插入到表尾
		r = i;
	}// for
	space[r].cur = 0;               // 尾结点的指针为空
	for(j=1; j<=n; ++j) {           // 依次插入B的元素,若不在当前表中,则插入,否则删除
		ElemType b;
		printf("输入集合B的第%d个元素:\n", j);  
		scanf("%c", &b);
		fflush(stdin);				// 清空缓冲区
		int p = S;
		int k = space[S].cur;       // k指向集合A中第一个结点(数组下标为2)
		while((k != space[r].cur) && (space[k].data != b)) {//在当前表中查找
			p = k;
			k = space[k].cur;
		}// while
		if(k == space[r].cur) {     // 当前表中不存在该元素,插入在r所指结点之后,且r的位置不变
			i = Malloc_SL(space);
			space[i].data = b;
			space[i].cur = space[r].cur;
			space[r].cur = i;
		}// if
		else {                      // 该元素已在表中,删除之
			space[p].cur = space[r].cur;
			Free_SL(space, k);
			if(r == k)  r = p;      // 若删除的是r所指结点,则需修改尾指针
		}// else
	}// for
}// difference 算法2.17

// 创建随机静态链表
void CreateList_SL(SLinkList space, int n) {
	InitSpace_SL(space);			// 将数组space各分量链成一个备用链表
	int header = Malloc_SL(space);  // 获取分配的结点下标(初次分配为结构体数组下标为1的元素),设为静态链表的头结点
	int pos = header;               // pos指向分配的结点(用来标记静态链表最后一个元素)
//	srand((unsigned)time(NULL));    // 初始化随机数种子
	for (int k=0; k<n; k++) {
		int index = Malloc_SL(space);// 获取备用链表中的空闲存储单元 对应在 结构体数组array[MAXSIZE]中的下标
		space[pos].cur = index;     // 静态链表最后一个结点 指向 新申请的空闲存储单元
//		space[index].data = rand()%1000;
		printf("请输入静态链表的第%d个字符数据:", k+1);
		scanf("%C", &space[index].data);
		fflush(stdin);				// 清空缓冲区
		pos = index;                // pos标记后移
	}
	space[pos].cur=0;               // 新的链表最后一个结点的指针设置为0
}// CreateList_SL

// 操作结果:创建一个带头结点的静态链表。
Status InitList_SL(SLinkList space) {
	InitSpace_SL(space);            // 将数组space各分量链成一个备用链表
	int header = Malloc_SL(space);  // 获取分配的结点下标(初次分配为结构体数组下标为1的元素),设为静态链表的头结点
	space[header].cur = 0;			// 静态链表头结点的游标置0
	return OK;
}// InitList_Sq

// 操作结果:销毁静态链表L。
Status DestroyList_SL(SLinkList space) {
	for(int i=0; i<MAXSIZE; i++) {
		space[i].cur = NULL;
		space[i].data = NULL;
	}
	return OK;
}// DestroyList_SL

// 操作结果:将L重置为空表。
Status ClearList_SL(SLinkList space) {
	for(int i=0; i<MAXSIZE; i++) {
		space[i].cur = NULL;
		space[i].data = NULL;
	}
	InitList_SL(space);
	return OK;
}// ClearList_SL

// 操作结果:若L为空表,返回TRUE,否则返回FALSE
Status ListEmpty_SL(SLinkList space) {
	if(space[1].cur == 0)           // 静态链表头结点游标是否为0
		return TRUE;
	else return FALSE;
}// ListEmpty_SL

// 操作结果:返回L中数据元素个数。
int ListLength_SL(SLinkList space) {
	int nElem = 0;
	int pos = 1;					// pos指向静态链表头结点(在数组中的下标)
	while(space[pos].cur) {
		pos = space[pos].cur;		// pos后移,直到表尾
		nElem++;
	}
	return nElem;
}// ListLength

// 操作结果:用e返回L中第i个数据元素的值。1≤i≤ListLength(L) 。
Status GetElem_SL(SLinkList space, int i, ElemType &e) {
	int pos = 1;					// pos指向静态链表头结点(在数组中的下标)
	// 则space[pos].cur指示静态链表的第二个结点(第1个元素)。
	// 当space[pos].cur=0时,此时的index为静态链表最后一个结点。
	while(space[pos].cur != 0) {	// 查找第i个数据元素
		if(pos == i)
			break;
		pos = space[pos].cur;
	}
	if(pos == 0)					// 未找到元素
		return ERROR;
	e = space[space[pos].cur].data;	// 返回数据
	return OK;
}// GetElem_SL

// 操作结果:返回L中第1个与数据元素e相同的位序(数组下标),若这样的数据元素不存在,则返回值为0。compare()是数据元素判定函数。
int LocateElem_SL(SLinkList space, ElemType e) {
	int i = space[1].cur;			// i为静态链表 第一个结点在数组中的下标,
	while( i && space[i].data != e)	// 在表中顺链查找
		i = space[i].cur;
	return i;
}// LocateElem_SL 算法2.13

// 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失败,pre_e无定义。
Status PriorElem_SL(SLinkList space, ElemType cur_e, ElemType &pre_e) {
    int i = LocateElem_SL(space, cur_e);
    if(space[i].cur==2) return ERROR;
	int pos = 1;
	while(space[pos].cur != 0) {	// 查找第i-1个数据元素在数组中的下标pos
		if(space[pos].cur == i)
			break;
		pos = space[pos].cur;
	}
	if(pos == 1)  return ERROR;
	pre_e = space[pos].data;
    return OK;
}// PriorElem_SL

// 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则操作失败,pre_e无定义。
Status NextElem_Sq(SLinkList space, ElemType cur_e, ElemType &next_e) {
    int i = LocateElem_SL(space, cur_e);
    if(space[i].cur==0) return ERROR;
	int nextIndex = space[i].cur;
	next_e = space[nextIndex].data;
    return OK;
}// NextElem_Sq

// 操作结果:在L中第pos个位置之前插入新的元素e,L的长度加1。1≤pos≤ListLength(L)+1。
Status ListInsert_SL(SLinkList space, int pos, ElemType e) {
	if (pos<1 || pos>ListLength_SL(space)+1)// 插入位置是否合法(插入的位置在表内)
		return ERROR;
	int tmpPos = 1;							// tmpPos指向静态链表头结点
	int index = Malloc_SL(space);			// 获取分配的结点下标
	if(index) {								// 判断备用链表中是否还有空闲存储单元
		for(int i=1; i<pos; i++)
			tmpPos = space[tmpPos].cur;		// 获取插入位置的下标
		space[index].data = e;				// 插入元素的值
		space[index].cur = space[tmpPos].cur;// 插入元素 指向 下一元素
		space[tmpPos].cur = index;			// 上一元素 指向 插入元素
		printf("插入的位置:%d, 插入的元素:%c\n", pos, e);
		return OK;
	}
	return ERROR;
}// ListInsert_SL

// 操作结果:删除L的第pos个数据元素,并用e返回其值,L的长度减1。1≤pos≤ListLength(L)。
Status ListDelete_SL(SLinkList space, int pos, ElemType &e) {
	if (pos < 1 || pos > ListLength_SL(space))  // 判断合法性
		return ERROR;
	int tmpPos = 1;							// tmpPos指向静态链表头结点
	for(int i=1; i<pos; i++)				// 获取删除位置的前一个元素的下标
		tmpPos = space[tmpPos].cur;
	int index_pre = tmpPos;					// 保存删除位置的前一个元素的下标
	int index_del = space[tmpPos].cur;		// 获取删除位置的下标
	e = space[index_del].data;
	space[index_pre].cur = space[index_del].cur;// 将删除位置的前一个元素链接到删除元素的后一个元素
	Free_SL(space, index_del);				// 将下标为index_del的空闲结点回收到备用链表
	printf("删除的位置:%d, 删除的元素:%c\n", pos, e);
	return OK;
}// ListDelete_SL

// 操作结果:依次对L的每个数据元素调用函数visit()。一旦vistit()失败,刚操作失败。
Status visit(SLinkList space, int pos, int i) {
	printf("%4d  %12d  %10c  %12d\n", i, pos, space[pos].data, space[pos].cur);
	return OK;
}
Status ListTraverse_SL(SLinkList space, Status (*pfn_visit)(SLinkList space, int pos, int i)) {
	// Status ListTraverse_SL(SLinkList space, int index) {
	if(space[0].cur == 0 || space[1].cur == 0)	{
		printf("线性表未初始化或为空表。\n");
		return ERROR;
	}
	int pos = 1;
	int i = 1;
	printf("\n元素序号――数组下标――存储数据――指向的数组下标\n");
	while(space[pos].cur) {
		pos = space[pos].cur;
		visit(space, pos, i++);
		//printf("%c %d ,", space[pos].data, space[pos].cur);
	}
	printf("\n");
	return OK;
}// ListTraverse_SL

int main()
{
	SLinkList staticList;
	// 创建4个元素的随机静态链表
	CreateList_SL(staticList, 4);

	// 遍历线性表
	ListTraverse_SL(staticList, visit);

	if(!ListEmpty_SL(staticList))
		printf("静态链表非空\n");	// 判空
	else
		printf("静态链表为空\n");
	printf("静态链表长度:%d\n", ListLength_SL(staticList));	// 求长

	// 销毁线性表
	DestroyList_SL(staticList);

	// 初始化静态链表
	InitList_SL(staticList);

	// 插入元素
	ListInsert_SL(staticList, 1, 'A');
	ListInsert_SL(staticList, 2, 'B');
	ListInsert_SL(staticList, 3, 'C');
	ListInsert_SL(staticList, 4, 'D');

	// 删除元素
	ElemType e;
	ListDelete_SL(staticList, 3, e);

	ListTraverse_SL(staticList, visit);	// 遍历线性表

	// 获取元素
	GetElem_SL(staticList, 3, e);
	printf("获取第3个元素:%c\n", e);

	ElemType pre_e, next_e;
	if(PriorElem_SL(staticList, 'B', pre_e))
		printf("元素B的前驱为:%c\n", pre_e);	

	if(NextElem_Sq(staticList, 'B', next_e))
		printf("元素B的后继为:%c\n", next_e);

	printf("元素B在数组中的下标为:%d\n", LocateElem_SL(staticList, 'B'));

	ClearList_SL(staticList);			// 清空线性表
	ListTraverse_SL(staticList, visit);	// 遍历线性表
	DestroyList_SL(staticList);			// 销毁线性表

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值