您的位置:首页 > 理论基础 > 数据结构算法

数据结构示例之带头节点的、单循环链表

2016-11-01 21:29 357 查看
以下为“带头节点的、单循环链表”的简单示例:

1. 用c语言实现的版本

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */
#include<stdlib.h> /* 申请和释放内存 */

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0

typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int ElemType;

/* 线性表的单链表存储结构 */
struct LNode
{
ElemType data;
struct LNode *next;
};

typedef struct LNode *LinkList; /* 另一种定义LinkList的方法 */

/* 构造一个空的、单向循环链表L */
Status InitList_CL(LinkList *L)
{
*L = (LinkList)malloc(sizeof(struct LNode)); /* 产生头结点,并使L指向此头结点 */
if (!*L) /* 存储分配失败 */
{
exit(OVERFLOW);
}
(*L)->next = *L; /* 指针域指向头结点 */
return OK;
}

/* 若L为空表,则返回TRUE,否则返回FALSE */
Status ListEmpty_CL(LinkList L)
{
if (L->next == L) /* 表尾指针所指元素的next值 等于 自身 */
{
return TRUE;
}
else
{
return FALSE;
}
}

/* 返回L中数据元素个数 */
int ListLength_CL(LinkList L)
{
int i = 0;
LinkList p = L->next; /* p指向头结点 */
while (p != L) /* 没到表尾 */
{
++i;
p = p->next;
}
return i;
}

/* 在L的第i个位置插入元素e */
Status ListInsert_CL(LinkList *L, int i, ElemType e) /* 改变L */
{
LinkList p = (*L)->next, s; /* p指向头结点 */
int j = 0;

if (i<1 || (i>ListLength_CL(*L) + 1)) /* 无法在第i个位置插入 */
{
return ERROR;
}

while (j < (i - 1)) /* 寻找第i-1个结点 */
{
p = p->next;
++j;
}
s = (LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */
/* 在第i个位置插入L中 */
s->data = e;
s->next = p->next;
p->next = s;

/* 改变尾结点 */
if (p == *L)
{
*L = s;
}

return OK;
}

/* 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
Status GetElem_CL(LinkList L, int i, ElemType *e)
{
int j = 1; /* 初始化,j为计数器 */
LinkList p = L->next->next; //由于L为带表头的、单向循环链表的表尾指针,所以p为第一个有效结点

if ((i < 1) || i > ListLength_CL(L)) /* 第i个元素不存在 */
{
return ERROR;
}

while (j<i)
{ /* 顺指针向后查找,直到p指向第i个元素 */
p = p->next;
++j;
}
*e = p->data; /* 取第i个元素 */

return OK;
}

/* 在L的第i个位置删除元素 */
Status ListDelete_CL(LinkList *L, int i)
{
LinkList p = (*L)->next, s; /* 由于L为带表头的、单向循环链表的表尾指针,所以p指向头结点 */
int j = 0;

if (i<1 || i>ListLength_CL(*L)) /* 无法删除第i个位置上的元素 */
{
return ERROR;
}

while (j < (i - 1)) /* 寻找第i-1个结点 */
{
p = p->next;
++j;
}

/* 删除第i个位置上的元素 */
s = p->next;
p->next = s->next;
/* 改变尾结点 */
if (s == *L)
{
*L = p;
}
free(s);

return OK;
}

/* 依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败 */
Status ListTraverse_CL(LinkList L, void(*vi)(ElemType))
{
LinkList p = L->next->next; //由于L为带表头的、单向循环链表的表尾指针,所以p为第一个有效结点
while (p != L->next)
{
vi(p->data);
p = p->next;
}
return OK;
}

/* 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失败,pre_e无定义 */
Status PriorElem_CL(LinkList L, ElemType cur_e, ElemType *pre_e)
{
LinkList q, p = L->next->next; //由于L为带表头的、单向循环链表的表尾指针,所以p为第一个有效结点
q = p->next;
while (q != L->next) /* p没到表尾 */
{
if (q->data == cur_e)
{
*pre_e = p->data;
return TRUE;
}
p = q;
q = q->next;
}
return FALSE;
}

/* 若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则操作失败,next_e无定义 */
Status NextElem_CL(LinkList L, ElemType cur_e, ElemType *next_e)
{
LinkList p = L->next->next; //由于L为带表头的、单向循环链表的表尾指针,所以p为第一个有效结点
while (p != L) /* p没到表尾 */
{
if (p->data == cur_e)
{
*next_e = p->next->data;
return TRUE;
}
p = p->next;
}
return FALSE;
}

/* 返回L中第1个与e满足关系compare()的数据元素的位序。若这样的数据元素不存在,则返回值为0 */
int LocateElem_CL(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
int i = 0;
LinkList p = L->next->next; //由于L为带表头的、单向循环链表的表尾指针,所以p为第一个有效结点
while (p != L->next)
{
++i;
if (compare(p->data, e)) /* 满足关系 */
return i;
p = p->next;
}
return 0;
}
// 比较函数
Status compare(ElemType c1, ElemType c2)
{
if (c1 == c2)
{
return TRUE;
}
else
{
return FALSE;
}
}

void visit(ElemType c)
{
printf("%d ", c);
}

/* 销毁线性表L */
Status DestroyList_CL(LinkList *L)
{
LinkList q, p = (*L)->next; /* 由于L为带表头的、单向循环链表的表尾指针,p指向头结点 */
while (p != *L) /* 没到表尾 */
{
q = p->next;
free(p);
p = q;
}
free(*L);
*L = NULL;
return OK;
}

/* 将L重置为空表 */
Status ClearList_CL(LinkList *L)
{
LinkList p, q;
*L = (*L)->next; /* 由于L为带表头的、单向循环链表的表尾指针,其后继结点为头结点 */
p = (*L)->next; /* p指向第一个结点 */
while (p != *L) /* 没到表尾 */
{
q = p->next;
free(p);
p = q;
}
(*L)->next = *L; /* 头结点指针域指向自身 */
return OK;
}

/* 合并两个单循环链表 */
void MergeList_CL(LinkList *La, LinkList Lb)
{
LinkList p = Lb->next; //由于Lb为带表头的、单向循环链表的表尾指针,所以p为单循环链表Lb的头节点
Lb->next = (*La)->next; //将单循环链表Lb的后继 更新为 La的头节点
(*La)->next = p->next; //将单循环链表la的后继 更新为 Lb的第一个有效节点
free(p); //释放 单循环链表Lb的头节点
*La = Lb; //将La的值 更新为 Lb的值,使两者都指向 合并后的 新链表的表尾
}

void main()
{
LinkList L,Lb;//带头节点的、单向循环链表的表尾指针
ElemType e;
int j;
Status i;

/* 初始化单循环链表L */
i = InitList_CL(&L);
if (i == OK)
{
printf("初始化单循环链表成功.\n");
}
else
{
printf("初始化单循环链表失败!\n");
return;
}

i = ListEmpty_CL(L);
if (i == OK)
{
printf("单循环链表为空.\n");
}
else
{
printf("单循环链表非空!\n");
}

ListInsert_CL(&L, 1, 3); /* 在L中第1个位置插入3 */
ListInsert_CL(&L, 2, 5); /* 在L中第2个位置插入5 */
ListInsert_CL(&L, 3, 7); /* 在L中第2个位置插入5 */

/* 获取第1个位置的元素 */
i = GetElem_CL(L, 1, &e);
if (i == OK)
{
printf("L中第%d个元素的值为%d。\n", 1, e);
}
else
{
printf("未能获取L中第%d个元素,请检查!\n", 1);
return ;
}
j = LocateElem_CL(L, 5, compare);
if (j)
{
printf("元素5的位置为%d\n", j);
}
else
{
printf("元素5不在单循环列表中\n");
}
//返回它的前驱
i = PriorElem_CL(L, 5, &j);
if (i == OK)
{
printf("L中元素%d的前驱为%d。\n", 5, j);
}
else
{
printf("未能获取L中元素%d的前驱(或者,它已是第一个元素,或该元素本是不存在)!\n", 5);
}

//返回它的后继
i = NextElem_CL(L, 5, &j);
if (i == OK)
{
printf("L中元素%d的后继为%d。\n", 5, j);
}
else
{
printf("未能获取L中元素%d的后继(或者,它已是最后一个元素,或该元素本是不存在)!\n", 5);
}

/* 返回L中数据元素个数 */
j = ListLength_CL(L);
printf("L中数据元素个数=%d。\n", j);

printf("L中的数据元素依次为:");
ListTraverse_CL(L, visit);

/* 在L的第1个位置删除元素 */
j = 3;
i = ListDelete_CL(&L, j);
if (i == OK)
{
printf("\n单循环链表成功删除第%d个元素.\n", j);
}
else
{
printf("\n单循环链表删除第%d个元素失败!\n", j);
return;
}
/* 返回L中数据元素个数 */
j = ListLength_CL(L);
printf("L中数据元素个数=%d。\n", j);

printf("L中的数据元素依次为:");
ListTraverse_CL(L, visit);

/* 将L重置为空表 */
i = ClearList_CL(&L);
if (i == OK)
{
printf("\n已经重置单循环链表\n");
}

/* 返回L中数据元素个数 */
j = ListLength_CL(L);
printf("重置后,L中数据元素个数=%d。\n", j);

/* 销毁单循环链表 */
i = DestroyList_CL(&L);
if (i == OK)
{
printf("已经销毁单循环链表,链表尾指针已经置为%0x.\n", L);
}
////////////////////////////////////////////////////////
////测试链表合并
i = InitList_CL(&L);
if (i == OK)
{
printf("初始化单循环链表成功.\n");
}
else
{
printf("初始化单循环链表失败!\n");
return;
}
ListInsert_CL(&L, 1, 3); /* 在L中第1个位置插入3 */
ListInsert_CL(&L, 2, 5); /* 在L中第2个位置插入5 */
ListInsert_CL(&L, 3, 7); /* 在L中第2个位置插入5 */

i = InitList_CL(&Lb);
if (i == OK)
{
printf("初始化单循环链表成功.\n");
}
else
{
printf("初始化单循环链表失败!\n");
return;
}
ListInsert_CL(&Lb, 1, 2); /* 在L中第1个位置插入3 */
ListInsert_CL(&Lb, 2, 4); /* 在L中第2个位置插入5 */
ListInsert_CL(&Lb, 3, 6); /* 在L中第2个位置插入5 */

MergeList_CL(&L, Lb); //合并两个单循环链表
printf("在合并后的单循环链表中,数据元素依次为:");
ListTraverse_CL(Lb, visit);
printf("\n");
}
运行结果如下图所示:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构