/* 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;
}
《数据结构》(C语言版)——线性表的静态单链表存储结构
最新推荐文章于 2024-04-19 21:02:49 发布