【大话数据结构】线性表:顺序表和链表

来源:互联网 发布:视频慢放软件下载 编辑:程序博客网 时间:2024/05/17 07:49

线性表(List):零个或多个数据元素的有限序列。

一般复杂操作基本可以用基本操作组合而成,比如GetElem、LocateElem、ListInsert、ListDelete、ListLength等。


顺序存储结构—顺序表

用一段地址连续的存储单元依次存储线性表的数据元素。比如C语言的一维数据。结构图示:


顺序存储结构的缺点是插入和删除时需要移动大量元素。

一般操作示例:

#define MAXSIZE 20typedef int ElemType;  /*元素类型假设为int*/typedef struct{ElemType data[MAXSIZE];    /*数组的长度,开辟存储空间长度,一般不变,初动态分配数组*/int length;                /*线性表当前长度,数据元素的个数,随着插入删除操作变化着*/}SqList;/*取数组L中第i个元素给e*/void GetElem(SqList L, int i, ElemType *e){if (L.length == 0 || i<1 || i>L.length)return;*e = L.data[i - 1];}/*在第i个元素前插入新的元素e,L的长度增加1*/void ListInsert(SqList *L, int i, ElemType e){int k;if (L->length == MAXSIZE || i<1 || i>L->length + 1)return;if (i <= L->length)        /*插入位置不在表尾时,把后面的元素均向后移动一位*/{for (k = L->length - 1; k >= i - 1; k--)L->data[k + 1] = L->data[k];}L->data[i - 1] = e;L->length++;}/*删除L的第i个元素,其值给e,长度减1*/void ListDelete(SqList *L, int i, ElemType *e){int k;if (L->length == 0 || i<1 || i>L->length)return;*e = L->data[i - 1];if (i < L->length)         /*删除的不是最后元素,后面元素向前移*/{for (k = i; k < L->length; k++)L->data[k - 1] = L->data[k];}L->length--;}


链式存储结构—链表

用一组任意的存储单元存储数据元素,这些存储单元可以是连续的,也可以是不连续的。

这就是链表。存储单元就是结点(Node)。结点 = 数据域 + 指针域(指示后继的存储位置),结构图示为:


以下是链表的几种:

单链表

单链表的结构(左)和 空链表的结构(右):

   

一般操作示例:

typedef struct Node{ElemType data;struct Node *next;}Node;typedef struct Node *LinkList;/*取链表中第i个数据元素的值给e*/void GetElem(LinkList L, int i, ElemType *e){LinkList p;         /*声明一结点p*/p = L->next;        /*让p指向链表L的第一个结点*/int j;j = 1;              /*计数器j*/while (p && j<i)    /*p不为空且j还没有到i*/{p = p->next;++j;}if (!p || j>i)return;     /*第i个元素不存在*/*e = p->data;}/*在链表L中第i个位置之前插入新的元素e,L长度加1*/void ListInsert(LinkList *L, int i, ElemType e){LinkList p, s;p = *L;int j;j = 1;while (p && j<i){p = p->next;++j;}if (!p)return;     /*第i个结点不存在*/s = (LinkList)malloc(sizeof(Node));s->data = e;s->next = p->next;p->next = s;}/*删除L的第i个元素,用e返回其值,L的长度减1*/void ListDelete(LinkList *L, int i, ElemType *e){LinkList p, q;p = *L;int j;j = 1;while (p->next && j<i){p = p->next;++j;}if (!p->next)        /*没有第i个元素*/return;q = p->next;p->next = q->next;*e = q->data;free(q);}

循环链表

循环链表是头尾相接的单链表。结构图示:

 或 

上图中,终端结点用【尾指针rear】指示,头结点是 rear->next,第一个结点是 rear->next->next


合并操作示例:

p = rearA->next;rearA->next = rearB->next->next;   /*将A的尾端指向B的第一个结点(不是头结点)*/rearB->next = p;   /*将B的尾端指向A的头结点*/free(p);

双向链表

双向链表就是单链表的结点中多加了一个指向前驱结点的指针。结构图示:


删除结点操作示例:

typedef struct DulNode{ElemType data;struct DulNode *prior; /*前驱指针*/struct DulNode *next;  /*后继指针*/}DulNode, *DuLinkList;/*双向链表的删除操作*/p->prior->next = p->next;p->next->prior = p->prior;free(p);