【大话数据结构】03 线性表 笔记

《大话数据结构》
——共463页

第 3 章 线性表

66页_开场白
66页_线性表定义
线性表的定义
线性表(List):零个或多个数据元素的有限序列。
——Date
除第一个元素a1外,每一个元素有且只有一个直接前驱元素,
除最后一个元素an外,每一个元素有且只有一个直接后继元素,
数据元素之间是一对一的关系
——Operation
InitList(*L): 初始化操作,建立一个空的线性表L.
ListEmpty(L): 若线性表为空,返回true,否则返回false.
ClearList(*L): 将线性表清空
GetElem(L,i,*e) 将线性表L的第i个位置元素值返回给e
LocateElem(L,e) 在线性表L中查找与给定值e相等的元素,如果查找成功,
返回该元素在表中序号表示成功;否则返回0表示失败
ListInert(*L,i,e) 在线性表L中的第i个位置插入新元素e
ListDelete(*L,i,*e) 删除线性表L中第i个位置元素,并用e返回其值
ListLength(L) 返回线性表L的元素个数

线性表的顺序存储结构
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。
#define MAXSIZE 20 //存储空间初始分配量
typedef int ElemType; //ElemType类型根据实际情况而定,这里假设为int*
typedef struct
{
ElemType date[MAXSIZE]; //输出存储数据元素,最大值为MAXSIZE
int length; //线性表当前长度
}SqList;
一般情况下,线性表的长度小于等于数组的长度。
地址计算:高级语言数组是由0开始,而线性表由1开始。
LOC表示获得存储位置的函数

获得元素操作
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
Status GetElem(SqList L,int i ElemType *e)
{
if(L.length==0 || i<1 || i>L.length)
return ERROR; //返回0
*e=L.data[i-1];
return OK; //返回1
}
判断顺序线性表是否存在
判断该位置是否存在
从顺序线性表中找到该位置的元素

插入操作
Status ListInsert(SqList *L,int i,ElemType e)
{
int k;
if(L->length==MAXSIZE) //顺序线性表已经满 ->指针值的传递
return ERROR;
if(i<1 || i>L->length+1) //当i不在范围内时
return ERROR;
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++;
return OK;
}

判断顺序线性表是否已经满
判断该位置是否存在
如果在表尾直接插入
如果不在表尾,把后继元素从表尾开始依次往后移动一位,再插入

删除操作
Status ListDelete(SqList *L,int i,ElemType *e)
{
int k;
if(L->length==0) //线性表为空
return ERROR:
if(i<1 || i>L->length) //删除位置不正确
return ERROR:
*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--;
return OK;
}

线性表顺序储存结构优缺点


80页_线性表链式储存结构定义
链表中第一个结点的存储位置叫做头指针,头指针是链表的必要元素。
单链表的第一个结点前附设一个结点,称为头结点。
头结点的数据域可以不存储任何信息或线性表长度等附加信息。





线性表的单链表存储结构
typedef struct Node
{
ElemTyoe data;
struct Node *next;
}Node;
typedef struct Node *LinkList; //定义LinkList

单链表的读取
Status GetElem(LinkList L,int i ,ElemType *e)
{
int j;
LinkList p; //声明一结点p
p =L->next; //让p指向链表L的第一个结点
j = 1; //j为计数器
while(p && j<i) //p不为空或者计数器j还没有等于i时,循环继续
{ //因为不知道需要循环几次,所以没办法用for
p = p->next; //让p指向下一个结点
++j;
}
if( !p || j>i) //如果p为空或者j大于i
return ERROR //第i个元素不存在
*e = p->data;
return Ok;
}
声明一个结点p指向链表第一个结点,初始化j从1开始;
当j<i时,就遍历链表,让p的指针向后移动,不断指向下一结点,


单链表的插入
Status ListInsert(LinkList *L,int i,ElemType e)
{
int j;
LinkList p,s;
p = *L;
j = 1;
while(p && j < i) //寻找第i个结点
{
p = p->next;
++j;
}
if(!p || j > i)
return ERROR; //第i个元素不存在
s = (LinkList)malloc(sizeof(Node))
//生成新的结点(c标准函数)
s->data = e;
s->next = p->next; //将p的后继结点赋值给s的后继
p->next = s; //将s赋值给p的后继
return Ok;
}


单链表的删除
Status ListDelete(LinkList *L,int i,ElemType e)
{
int j;
LinkList p,q;
p = *L;
j = 1;
while(p->next && j < i) //寻找第i个结点
{
p = p->next;
++j;
}
if(!(p->next) || j > i)
return ERROR; //第i个元素不存在
q = p->next;
p->next = q->next; //生成新的结点(c标准函数)
*e = q->data; //将q结点中的数据给e
free(q); ; //让系统回收此结点,释放内存
return Ok;
}

单链表的整表创建
//随机产生n个元素的值,建立带表头结点的单链线性表L (头插法)
void CreateListHead(LinkList *L,int n)
{
LinkList p;
int i;
srand(time(0)); //初始化随机数种子
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL; //先建立一个带头结点的单链表
for(i=0;i<n;i++)
{
p = (LinkList)malloc(sizeof(Node))//生成新结点
p->data = rand()%100+1; //随机生成100以内的数字
p->next = (*L)->next;
(*L) ->next = p; //插入到表头
}
}
//还有 (尾插法),即将尾端结点指向新结点,定义新结点为终端,循环后终端指向为空

单链表的整表删除
Status ClearList(LinkList *L)
{
LinkList p,q;
p=(*L)->next; //p指向第一个结点
while(p) //没到表尾
{
q=p->next;
free(p);
p=q;
}
(*L)->next=NULL; //头结点指针域为空
return OK;
}

单链表结构与顺序存储结构优缺点


95页_静态链表
静态链表
c语言具有指针能力,java、c#不用指针却有对象引用机制,basic、fortran等早期语言就可以用数组代替指针。
用数组描述的链表叫做静态链表
将所有未被使用过的及已被删除的分量用游标链成一个备用的链表


静态链表的插入操作
通过改游标和备用链表实现


静态链表的删除操作


静态链表优缺点


103页_循环链表
将单链表中终端结点的指针端由空指针改为指向头结点,就像整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。解决了如何从当中一个结点出发,访问到链表的全部结点。

双向链表
双向链表是在单链表的每一个结点中,再设置一个指向其前驱结点的指针域

总结


猜你喜欢

转载自blog.csdn.net/jvao_q7/article/details/80063627