线性表的链式表示和实现----循环(单)链表

来源:互联网 发布:中兴 南京 云计算部门 编辑:程序博客网 时间:2024/06/05 09:15
<span style="font-family: Arial, Helvetica, sans-serif;">头文件 head.h</span>
<span style="font-family: Arial, Helvetica, sans-serif;"></span>
<span style="font-family: Arial, Helvetica, sans-serif;">#include<string.h></span>
#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<limits.h> /* INT_MAX等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<io.h> /* eof() */#include<math.h> /* floor(),ceil(),abs() */#include<process.h> /* exit() *//* 函数结果状态代码 */#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef int ElemType;typedef struct LNode_CL{ElemType data;struct LNode_CL *next;}LNode_CL;typedef struct LNode_CL *LinkList_CL;Status InitList_CL(LinkList_CL *L);Status DestoryList_CL(LinkList_CL *L);Status ClearList_CL(LinkList_CL *L);Status ListEmpty_CL(LinkList_CL L);int ListLength_CL(LinkList_CL L);Status GetElem_CL(LinkList_CL L, int i, ElemType *e);int LocateElem_CL(LinkList_CL L, ElemType e);Status PriorElem_CL(LinkList_CL L, ElemType cur_e, ElemType *pre_e);Status NextElem_CL(LinkList_CL L, ElemType cur_e, ElemType *next_e);Status ListInsert_CL(LinkList_CL *L, int i, ElemType e);Status ListDelet_CL(LinkList_CL *L, int i, ElemType *e);Status ListTraverse_CL(LinkList_CL L);
Status MergeList(LinkList_CL *La, LinkList_CL Lb);


算法实现


#include"head.h"/*由于表尾容易找到表头,但若链表较长,则由表头找到表尾比较耗时,因而,单循环链表往往设立尾指针而不是头指针,其中尾指针指向最后一个结点也就是说,单循环链表最少应该有一个头结点(不是第一个结点)和尾指针,因为是循环链表,空表就相当于头结点中的指针是尾指针,非空表则不同!*/Status InitList_CL(LinkList_CL *L){//操作结果:构造一个空的线性表L*L = (LinkList_CL)malloc(sizeof(LNode_CL));if (!(*L)){printf("循环列表初始化失败!\n");exit(-1);}(*L)->next = (*L);//和单链表的不同之处return OK;}Status DestoryList_CL(LinkList_CL *L){//初始条件:线性表L已存在//操作结果:将L重置为空表LinkList_CL p, q = (*L)->next;//q指向(*L)的头结点while (q != (*L))//判定不是空链表!!!!{p = q->next;//第一次循环时指的是第一个结点free(q);q = p;}free(*L);*L = NULL;//最后别忘了将表制空return OK;}Status ClearList_CL(LinkList_CL *L){//初始条件:线性表L已存在//操作结果:将L重置为空白LinkList_CL 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;}Status ListEmpty_CL(LinkList_CL L){//初始条件:线性表已存在//操作结果:若L为空表,则返回TRUE;否则,返回FALSELinkList_CL p = L->next;if (p != L)return FALSE;elsereturn TRUE;}int ListLength_CL(LinkList_CL L){//初始条件:线性表L已存在//操作结果:返回L中元素的个数int n = 0;L = L->next;//指向头结点LinkList_CL p = L->next;//指向第一个元素while (p != L)//没有到表尾{n++;p = p->next;}return n;}Status GetElem_CL(LinkList_CL L, int i, ElemType *e){//初始条件:线性表L已存在, 1<= i <=ListLength(L)+1//操作结果:用e返回L中第i个数据元素的值int n = 1;LinkList_CL p;if (i<1 || i>ListLength_CL(L) + 1)return FALSE;L = L->next;//头结点p = L->next;//第一个结点while (n < i){p = p->next;n++;}*e = p->data;return OK;}int LocateElem_CL(LinkList_CL L, ElemType e){int n = 1;LinkList_CL p;L = L->next;//头结点p = L->next;//第一个结点while (p != L){if ((p->data) == e)return n;n++;p = p->next;}return 0;}Status PriorElem_CL(LinkList_CL L, ElemType cur_e, ElemType *pre_e){LinkList_CL p, q;p = L->next->next; //第一个元素q = p->next;//第二个元素while (q != L->next)//没有到表尾{if (q->data == cur_e){*pre_e = p->data;return TRUE;}p = q;q = q->next;}return FALSE;}Status NextElem_CL(LinkList_CL L, ElemType cur_e, ElemType *next_e){LinkList_CL p;p = L->next; p = p->next;//指向第一个元素while (p != L)//没有到表尾{if (p->data == cur_e){p = p->next;*next_e = p->data;return TRUE;}p = p->next;}return FALSE;}Status ListInsert_CL(LinkList_CL *L, int i, ElemType e){int n = 1;LinkList_CL t = (*L)->next;//t代表头结点LinkList_CL s;if (i<1 || i>ListLength_CL(*L) + 1)return FALSE;while (n < i)//找到i之前的那一个位置{t = t->next;n++;}s = (LinkList_CL)malloc(sizeof(LNode_CL));s->data = e;s->next = t->next;//由后向前处理数据t->next = s;if (t == *L)//改变尾结点????//如果在表尾处插入该元素,则应该改变尾指针是指指向新增加的元素*L = s;return OK;}Status ListDelet_CL(LinkList_CL *L, int i, ElemType *e){LinkList_CL p = (*L)->next, t;//p为头结点int n = 1;if (i<1 || i>ListLength_CL(*L))return FALSE;while (n < i)//找到i之前的那个位置{p = p->next;n++;}t = p->next;*e = t->data;p->next = t->next;//如果删除是表尾元素if (*L = t)//则尾指针指向被删除元素(表尾元素)的前一个结点的指针*L = p;free(t);return OK;}Status ListTraverse_CL(LinkList_CL L){LinkList_CL p;L = L->next;//头结点p = L->next;//第一个结点while (p != L){printf("%d  ", p->data);p = p->next;}printf("\n");return OK;}
Status MergeList(LinkList_CL *La, LinkList_CL Lb){<span style="white-space:pre"></span>//将Lb合并到La的表尾,由La指示新表, 中间两行注释的代码有些冗余,因为尾指针的下一个元素是头结点是循环链表固有的属性!<span style="white-space:pre"></span>LinkList_CL p = Lb->next;<span style="white-space:pre"></span>//指向Lb的头结点//<span style="white-space:pre"></span>LinkList_CL q = (*La)->next;<span style="white-space:pre"></span>Lb->next = (*La)->next;<span style="white-space:pre"></span>(*La)->next = p->next;<span style="white-space:pre"></span>//Lb的头结点是多余的,去除即可<span style="white-space:pre"></span>free(p);//<span style="white-space:pre"></span>Lb->next = q;<span style="white-space:pre"></span>(*La) = Lb;<span style="white-space:pre"></span>//改变La的尾指针<span style="white-space:pre"></span>return OK;}

测试文件1 test.c

#include"head.h"void main() /* 除了几个输出语句外,主程和main2-1.c很像 */{LinkList_CL L; /* 与main2-1.c不同 */ElemType e, e0;Status i;int j, k;i = InitList_CL(&L);for (j = 1; j <= 5; j++)i = ListInsert_CL(&L, 1, j);printf("在L的表头依次插入1~5后:L=");ListTraverse_CL(L); /* 依次对元素调用visit(),输出元素的值 */i = ListEmpty_CL(L);printf("\nL是否空:i=%d(1:是 0:否)\n", i);i = ClearList_CL(&L);printf("清空L后:L=");ListTraverse_CL(L);i = ListEmpty_CL(L);printf("L是否空:i=%d(1:是 0:否)\n", i);for (j = 1; j <= 10; j++)ListInsert_CL(&L, j, j);printf("在L的表尾依次插入1~10后:L=");ListTraverse_CL(L);GetElem_CL(L, 5, &e);printf("\n第5个元素的值为:%d\n", e);//检测LocateElem_Lfor (j = 0; j <= 1; j++){k = LocateElem_CL(L, j);if (k)printf("第%d个元素的值为%d\n", k, j);elseprintf("没有值为%d的元素\n", j);}for (j = 1; j <= 2; j++) /* 测试头两个数据 */{GetElem_CL(L, j, &e0); /* 把第j个数据赋给e0 */i = PriorElem_CL(L, e0, &e); /* 求e0的前驱 */if (i == FALSE)printf("元素%d无前驱\n", e0);elseprintf("元素%d的前驱为:%d\n", e0, e);}for (j = ListLength_CL(L) - 1; j <= ListLength_CL(L); j++)/*最后两个数据 */{//printf("j=%d\n", j);GetElem_CL(L, j, &e0); /* 把第j个数据赋给e0 *///printf("元素wei%d\n", e0);i = NextElem_CL(L, e0, &e); /* 求e0的后继 */if (i == FALSE)printf("元素%d无后继\n", e0);elseprintf("元素%d的后继为:%d\n", e0, e);}k = ListLength_CL(L); /* k为表长 */for (j = k + 1; j >= k; j--){i = ListDelet_CL(&L, j, &e); /* 删除第j个数据 */if (i == FALSE)printf("删除第%d个数据失败\n", j);elseprintf("删除的元素为:%d\n", e);}printf("依次输出L的元素:");ListTraverse_CL(L);DestoryList_CL(&L);printf("\n销毁L后:L=%u\n", L);system("pause");}

Running result:

在L的表头依次插入1~5后:L=5  4  3  2  1L是否空:i=0(1:是 0:否)清空L后:L=L是否空:i=1(1:是 0:否)在L的表尾依次插入1~10后:L=1  2  3  4  5  6  7  8  9  10第5个元素的值为:5没有值为0的元素第1个元素的值为1元素1无前驱元素2的前驱为:1元素9的后继为:10元素10无后继删除第11个数据失败删除的元素为:10依次输出L的元素:1  2  3  4  5  6  7  8  9销毁L后:L=0请按任意键继续. . .

测试文件2 test2.c

#include"head.h"void main() /* 除了几个输出语句外,主程和main2-1.c很像 */{int n = 5;LinkList_CL La, Lb;//初始化LaInitList_CL(&La);for (int i = 1; i <= n; i++)ListInsert_CL(&La, i, i);printf("La = ");ListTraverse_CL(La);//初始化LbInitList_CL(&Lb);for (int i = 1; i <= n; i++)ListInsert_CL(&Lb, i, i*2);printf("Lb = ");ListTraverse_CL(Lb);if (MergeList(&La, Lb)){printf("La + Lb = ");ListTraverse_CL(La);}system("pause");}


Running Result:


La = 1  2  3  4  5Lb = 2  4  6  8  10La + Lb = 1  2  3  4  5  2  4  6  8  10请按任意键继续. . .



0 0
原创粉丝点击