线性表【03】线性表的链式表示与实现
2013-03-28 16:27
309 查看
线性表的表示与实现-------链式结构
链表:顺序查找,插入删除操作效率高。单链表
用一组地址任意的存储单元存放线性表中的数据元素。在物理上不一定相邻。
结点(表示数据元素或数据元素的映象)=元素(数据元素的映象) + 指针(指示后继元素存储位置)
以“结点的序列”表示线性表 称作链表
线性表的地址(线性表的头指针)是以线性表中第一个数据元素的存储地址
单链表的描述定义
Typedef struct LNode { ElemType data; // 数据域 struct Lnode *next; // 指针域 } LNode, *LinkList; LNode为结点 LinkList为指向链表的指针 LinkList L; // L 为单链表的头指针,是一个地址
要注意的是:以上定义了一个单链表,是一个地址,逻辑上的地址,而不是物理上的空间。
线性表的基本操作在链表中的实现(初始化、插入、删除、取元素、重置、创建)
注意:在单链表中通常会有一个头指针L,这个L所指的结点并不是第一个结点,头结点为21,P是一个指针,用来指向结点地址的指针。
初始化
Status InitList(LinkList &L){ L=(LinkList)malloc(sizeof(LNode)); //分配一个结点的空间 L->next=NULL; //将头指针指向的下一个结点(首元结点也是第一个结点)设为空 return OK; }
取元素
Status GetElem_L(LinkList L, int i, ElemType &e) { // L是带头结点的链表的头指针,以 e 返回第 i 个元素 p= L->next; j = 1; // p指向第一个结点,j为计数器,L->next为下一个结点 while (p && j<i) { pp = p->next; ++j; // 顺指针向后查找,直到 p 指向第 i 个元素 } // 或 p 为空 if ( !p || j>i ) return ERROR; // 第 i 个元素不存在 e = p->data; // 取得第 i 个元素 return OK; } // GetElem_L
插入
在链表中插入结点只需要修改指针,不需要移动大量元素,因为链表是一个指向。如上图:将ai-1的后继指针指向e.
Status ListInsert_L(LinkList L, int i, ElemType e) { // L 为带头结点的单链表的头指针,本算法 // 在链表中第i 个结点之前插入新的元素 e p = L; j = 0; while (p && j < i-1) { pp = p->next; ++j; // 寻找第 i-1 个结点 } if (!p || j > i-1) return ERROR; // i 大于表长或者小于1 s = (LinkList) malloc ( sizeof (LNode)); // 生成新结点 s->data = e; s->next=NULL; //让s指向结点e s->next = p->next; p->next = s; // 插入,过程如下图。 return OK; } // LinstInsert_L
删除
找到线性表中第i-1个结点,修改其指向后继的指针。
Status ListDelete_L(LinkList L, int i, ElemType &e) { // 删除以 L 为头指针(带头结点)的单链表中第 i 个结点 p = L; j = 0; while (p->next && j < i-1) { pp = p->next; ++j; // 寻找第 i 个结点,并令 p 指向其前趋 } if (!(p->next) || j > i-1) return ERROR; // 删除位置不合理 q = p->next; p->next = q->next; // 删除并释放结点,过程如下图 e = q->data; free(q); return OK; } // ListDelete_L
重置(将表置空)
void ClearList(&L) { // 将单链表重新置为一个空表 while (L->next) { p=L->next; L->next=p->next; free(p); } } // ClearList
创建
创建链表实际上就是一个插入的过程。过程如下:采用逆位序插入,然后建立头结点
void CreateList_L(LinkList &L, int n) { // 逆序输入 n 个数据元素,建立带头结点的单链表 L = (LinkList) malloc (sizeof (LNode)); L->next = NULL; // 先建立一个带头结点的单链表 for (i = n; i > 0; --i) { p = (LinkList) malloc (sizeof (LNode)); scanf(&p->data); // 输入元素值 p->next = L->next; L->next = p; // 插入 } } // CreateList_L 算法的时间复杂度为:O(Listlength(L))
循环链表
最后一个结点的指针域的指针又指回头结点(第一个结点)的链表,整个链表形成一个环注意:判断时应该是后继是否为头结点,比如取元素长度时,单链表为结点后继是否为NULL,但是循环链表的判断是结点的后继是否为头结点。
与单链表操作比较:
1.Initlist() 初始化时,头结点的next不为NULL,而是指向自身。
2.求表长:while中的条件改为 p!=L;
3.插入、删除操作的基本语句无变化
操作基本一致,通常遇到的循环条件不是判断指针p或p->next 是否为NULL,而是判断它们是否等于头结点
双向链表
定义
typedef struct DuLNode { ElemType data; // 数据域 struct DuLNode *prior; // 指向前驱的指针域 struct DuLNode *next; // 指向后继的指针域 } DuLNode, *DuLinkList;
双向循环链表
双向循环链表的基本操作:
其中查询和单链表相同。初始化
Status Init_Dul(DulinkList &L){ if(!L) return ERROR; L->next=L; L->prior=L; Return OK; }//Init_Dul
插入
不论P指向哪个结点,都要按照1234的顺序来就不会有错误
Status ListInsert_Dul(DuLinkList &L,int i, ElemType e){ P=L-->next; j=1; while(p&&j<i){ pp=p-->next; j++; } if(!p||j>i) return ERROR; if(!(s=(DuLinkList)malloc(sizeof(DuLNode))) return ERROR;) S-->data=e; S-->pprior=p ; S-->next= P-->next ; P-->next=S; S-->next-->prior=S ; return OK; }//
删除
删除中间结点
p-->next=p-->next-->next; p-->next-->pprior=p; 注意:现在的p-->next已经是最后一个结点了,因为上一步
相关文章推荐
- 02_线性表的链式表示和实现
- 线性表的表示和实现方式之链式表示和实现
- 线性表的链式表示和实现
- 第2章 线性表——链式线性表的表示和实现
- 数据结构算法代码实现——线性表的链式表示与实现(单链表)(三 )
- 线性表的链式表示和实现(数据结构)
- 数据结构(2):线性表的链式表示和实现
- 线性表的表示和实现方式之链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现(1)
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 数据结构--线性表的链式表示与实现
- 数据结构------线性表的链式表示与实现
- 严蔚敏--线性表的链式表示和实现 代码
- 线性表的链式表示和实现
- 线性表的链式表示与实现(单链表)
- 线性表的链式表示及实现
- 数据结构之线性表的链式表示和实现
- 线性表链式存储结构的表示和实现