1、存储方式:
用任意存储空间单元来存放线性表的各个元素,为了能体现元素之间的逻辑关系(线性),在存放每个元素的同时,也存放相关元素的信息(相关元素的存储地址),即用指针来表示元素之间的逻辑关系。存储一个元素占用的空间称为一个结点。
2、特点:
1)存储空间不一定连续;
2)逻辑关系是由指针来体现的;
3)逻辑上相邻,物理上不一定相邻;
4)非随机存取(顺序存取),即访问任何一个元素的时间不同;
3、分类:
单链式存储结构:存放元素的同时,存放其后继(或前驱)元素的信息;
双链式存储结构:存放元素的同时,存放其前驱后后继元素的信息;
循环单链式存储结构:在单链式存储结构中,由于最后一个元素没有后继,其结点 的指针域为空,若在此记下第一个元素的存储地址,则形成循环单链式存储结构;
循环双链式存储结构:在双链式存储结构中,最后一个元素结点的后继指针指向第一个元素结点,第一个元素的前驱指针指向最后一个元素结点。
4、术语
头指针:第一个元素的存储地址;
头结点:有时为了方便,增加一个结点,其数据域不存放任何元素,其指针域存放第一个元素的存储地址;
头结点指针:指向头结点的指针;
5、虚拟实现:
利用高级语言中的动态存储结构(即指针)来实现。
//---线性表的单链式存储结构--- typedef struct LNode { ElemType data; struct Lnode *next; }LNode, *LinkList;
6、实现:
1)初始化
//不带头结点
int Initlist(LinkList L) { L=NULL; return OK; }//带头结点
int Initlist(LinkList L)
{
L=(LNode*) malloc (sizeof(Lnode));
L->next=NULL;
reutrn OK;
}
2)求长度
int length_L(LinkList L) { i=0;//计数 p=L->next; while(P) { i++ p=p->next; } return i; }
3)访问第i个元素
由于仅仅知道第一个元素的存储地址,第i个元素的地址不象顺序存储那样可以立即计算出来,所以必须利用元素的后继指针去找到指定元素的存储地址,然后访问它!
即从头开始遍历每个元素,并且记数,看是否是指定元素。
Status GetElem_L(LinkList L, int i, ElemType &e) { P=L->next; j=1; while(p&&j<1) { p=p->next; ++j; } if(!p||j>i) return ERROR; e=p->data; return OK; }
4)插入某一个元素
Status Listinsert_L(LinkList &L, int i, ELemType e) { //在带头结点的单链表L中第i个位置之前插入元素e p=L;j=0; while(p&&j<i-1){p=p->next; ++j;} if(!p||j>i-1)return ERROR; s=(LinkList)malloc(sizeof(LNode)); s->data=e;s->next=p->next; p->next=s; reuturn OK; }
5)删除p指元素的后继元素 p->next=p->next->next
删除第i个元素:
Statuc ListDelete_L(LinkList &L, int i, ElemType &e) //在带头结点的单链线性表L中,删除第i个元素,并由e返回其值 { p=L;j=0; while(p->next&&j<i-1){p=p->next; ++j;} if(!(p-next)||j>i-1)return ERROR; q=p->next;p->next=q->next;//或p->next=p->next->next e=q-data;free(q); return OK; }
6)建立 输入线性表元素,以单链式存储方式存储,即创建单链表。
方法1:从头到尾,即从第一个元素结点逐个创建各个元素结点。每次都是链到当前链表的最后。
//创建头结点 L=(LinkList)malloc(sizeof(LNode)); L->next=NULL; r=L; //读入一个元素,链入其中 p=(LinkList)malloc(sizeof(LNode)); scanf(&p->data); p->next=NULL; r->next=p; r=r->next;方法2:从尾到头,即从最后一个元素结点逐个创建各个元素结点。每次都是链到当前链表的前面,即头结点之后。
//创建头结点 L=(LinkList)malloc(sizeof(LNode)); L->next=NULL; //读入一个元素,链入其中 p=(LinkList)malloc(sizeof(LNode)); scanf(&p->data); p->next=L->next;//使p->next为空 L->next=p;
7)归并 方法:可以在两个表上直接做,不需要开辟新空间,改变指针即可。
//归并 void MergeList_L(LinkList &La,LinkList &Lb, LinkList &Lc) { pa=La->next;pb=Lb->next; Lc=pc=La; while(pa&pb) { if(pa->data<=pb->data) { pc->next=pa;pc=pa;pa=pa->next; } else{pc->next=pb;pc=pb;pb=->next;} } pc->next=pa?pa:pb; free(Lb); }
8、小结
线性表的链式存储结构的方式,特点,分类
线性表的单链式存储结构的虚拟实现
线生表在单链式存储结构下操作的实现
(如:初始化,求表长,取表中第i个元素,插入,删除,建立链表,归并等)
9、拓展 双链表
特点:具有单链表的特点 前驱操作简单 任何位置插入、删除都简单了(已知该位置指针)
虚拟实现:
typedef struct DuLNode { ElemType data; struct DulNode *next; struct DulNode *prior; }DulNode, *DuLinkList;
循环双链式存储结构…。