[数据结构]第二章--线性表(读书笔记2)

来源:互联网 发布:知茵女装网上有卖吗 编辑:程序博客网 时间:2024/05/21 06:24

2.3 线性表的链式表示和实现

□什么是线性表的链式表示
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。线性链表的最后一个结点的指针为空(NULL)。若线性表为空表,则头结点的指针域为"空"。
删除结点:删除指针P所指结点后的结点。p->next = p->next->next;
如何删除首结点:可以加一个虚拟头结点。
插入链表:temp为即将插入新元素。temp->next = node->next;node->next = temp;
删除链表:pre->next = node->next;free(node);
单链表是非随机存取的存储结构。
循环链表(circular linked list):是另一种形式的链式存储结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。
双向链表(double linked list):为克服单链表这种单向性的缺点,就产生了双向链表。

/* 线性表的单链表存储结构 */typedef struct LNode{ElemType data;struct LNode *next;}LNode, *LinkList;Status InitList(LinkList *L){ /* 操作结果:构造一个空的线性表L */*L=(LinkList)malloc(sizeof(struct LNode)); /* 产生头结点,并使L指向此头结点 */if (!(*L)){/* 存储分配失败 */exit(OVERFLOW);}(*L)->next = NULL;/* 指针域为空 */return OK;}Status DestroyList(LinkList *L){ /* 初始条件:线性表L已存在。操作结果:销毁线性表L */LinkList q;while(*L){q = (*L)->next;free(*L);*L = q;}return OK;}Status ClearList(LinkList L) /* 不改变L */{ /* 初始条件:线性表L已存在。操作结果:将L重置为空表 */LinkList p = NULL;LinkList q = NULL;p = L->next; /* p指向第一个结点 */while (p){/* 没到表尾一直循环 */q = p->next;free(p);p = q;} /* 头结点指针域为空 */L->next = NULL;return OK;}Status ListEmpty(LinkList L){ /* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */if (L->next){return FALSE;}else{return TRUE;}}int ListLength(LinkList L){ /* 初始条件:线性表L已存在。操作结果:返回L中数据元素个数 */int len = 0;LinkList p = NULL;p = L->next;while (p){p = p->next;len++;}return len;}Status GetElem(LinkList L, int i, ElemType *e) /* 算法2.8 */{ /* L为带头结点的单链表的头指针。当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */int count = 1;LinkList p = L->next;if (i < 1){return ERROR;}/* 顺指针向后查找,直到p指向第i个元素或p为空 */while (p && count != i){p = p->next;count++;}/* 第i个元素不存在 */if( !p || count > i ){return ERROR;}*e = p->data;/* 取第i个元素 */return OK;}int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType,ElemType)){/* 初始条件: 线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0) *//* 操作结果: 返回L中第1个与e满足关系compare()的数据元素的位序。 *//*           若这样的数据元素不存在,则返回值为0 */LinkList p = NULL;int count = 1;p = L->next;while(p){if (compare(p->data, e)){break;}p = p->next;count++;}if (!p){return 0;}else{return count;}}Status PriorElem(LinkList L, ElemType cur_e, ElemType *pre_e){/* 初始条件: 线性表L已存在 *//* 操作结果: 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, *//*           返回OK;否则操作失败,pre_e无定义,返回INFEASIBLE */LinkList p = NULL;LinkList q = NULL;/* q为p的前驱 */p = L->next;/* p指向第一个结点 */q = L;while( p ){if ( p->data == cur_e ){break;}q = q->next;p = p->next;}if (p){*pre_e = q->data; return OK;}else{return INFEASIBLE;}}Status NextElem(LinkList L, ElemType cur_e, ElemType *next_e){/* 初始条件:线性表L已存在 *//* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, *//*           返回OK;否则操作失败,next_e无定义,返回INFEASIBLE */LinkList p = L->next;while( p ){if ( p->data == cur_e ){break;}p = p->next;}if (p && p->next){*next_e = p->next->data; return OK;}else{return INFEASIBLE;}}Status ListInsert(LinkList L, int i, ElemType e) /* 算法2.9。不改变L */{ /* 在带头结点的单链线性表L中第i个位置之前插入元素e */int count = 1;LinkList p = L;if ( i < 1 ){return ERROR;}while ( p ){if (i == count){break;}count++;p = p->next;}if ( !p ){return ERROR;}/* 生成新结点 */LinkList pNode = (LinkList )malloc(sizeof(struct LNode));pNode->data = e;/* 插入L中 */pNode->next = p->next;p->next = pNode;return OK;}Status ListDelete(LinkList L, int i, ElemType *e) /* 算法2.10。不改变L */{ /* 在带头结点的单链线性表L中,删除第i个元素,并由e返回其值 */int count = 1;LinkList p = L->next;LinkList q = L;if ( i < 1 ){return ERROR;}while ( p ){if (i == count){break;}count++;p = p->next;q = q->next;}if ( !p ){/* 删除位置不合理 */return ERROR;}/* 删除并释放结点 */*e = p->data;q->next = p->next;free(p);return OK;}Status ListTraverse(LinkList L,void(*vi)(ElemType))/* vi的形参类型为ElemType,与bo2-1.c中相应函数的形参类型ElemType&不同 */{/* 初始条件:线性表L已存在 *//* 操作结果:依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败 */LinkList p = L->next;while ( p ){vi(p->data);p = p->next;}printf("\n");return OK;}/*判断用辅助函数*/Status comp(ElemType c1,ElemType c2) /* 数据元素判定函数(平方关系) */{if(c1 == c2 * c2){return TRUE;}else{return FALSE;}}/*输出用辅助函数*/void visit(ElemType c) /* ListTraverse()调用的函数(类型要一致) */{printf("%d ",c);}int _tmain(int argc, _TCHAR* argv[]){LinkList L; /* 与main2-1.c不同 */ElemType e,e0;Status i;int j,k;i=InitList(&L);for(j=1;j<=5;j++){i=ListInsert(L,1,j);}printf("在L的表头依次插入1~5后:L=");ListTraverse(L,visit); /* 依次对元素调用visit(),输出元素的值 */i = ListEmpty(L);printf("L是否空:i=%d(1:是 0:否)\n",i);i = ClearList(L);printf("清空L后:L=");ListTraverse(L,visit);i=ListEmpty(L);printf("L是否空:i=%d(1:是 0:否)\n",i);for(j = 1; j <= 10; j++){ListInsert(L,j,j);}printf("在L的表尾依次插入1~10后:L=");ListTraverse(L,visit);GetElem(L, 5, &e);printf("第5个元素的值为:%d\n",e);for(j = 0;j <= 1;j++){k=LocateElem(L,j,comp);if(k){printf("第%d个元素的值为%d\n",k,j);}else{printf("没有值为%d的元素\n",j);}}for(j = 1;j <= 2;j++) /* 测试头两个数据 */{GetElem(L,j,&e0); /* 把第j个数据赋给e0 */i=PriorElem(L,e0,&e); /* 求e0的前驱 */if(i == INFEASIBLE){printf("元素%d无前驱\n",e0);}else{printf("元素%d的前驱为:%d\n",e0,e);}}for(j=ListLength(L)-1;j<=ListLength(L);j++)/*最后两个数据 */{GetElem(L,j,&e0); /* 把第j个数据赋给e0 */i=NextElem(L,e0,&e); /* 求e0的后继 */if(i==INFEASIBLE){printf("元素%d无后继\n",e0);}else{printf("元素%d的后继为:%d\n",e0,e);}}k=ListLength(L); /* k为表长 */for(j=k+1;j>=k;j--){i=ListDelete(L,j,&e); /* 删除第j个数据 */if(i==ERROR){printf("删除第%d个数据失败\n",j);}else{printf("删除的元素为:%d\n",e);}}printf("依次输出L的元素:");ListTraverse(L, visit);DestroyList(&L);printf("销毁L后:L=%u\n",L);return 0;}
原创粉丝点击