严蔚敏视频 笔记05
链表的生成操作
void CreateList_L(LinkList &L,int 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; // 插入到表头
}
}
时间复杂度为:O(ListLength(L))
基本操作 计数器和指针的关系
void union(List &La,List &Lb) {
La len=ListLength(La);
Lb len=ListLength(Lb);
for(i=1;i<=Lb_len;i++) {
GetElem(Lb,i,e);
if(!LocateElem(La.e,equal()))
ListInsert(La,++La_len,e);
}
时间复杂度:
控制结构:for循环
基本操作:LocateElem(La,e,equal())
顺序映象时 时间复杂度为O(n^2)
链式映象时 时间复杂度为O(n^2)
void purge(List &La,List Lb) {
InitList(La);
La_len=ListLength(La); Lb_len=ListLength(Lb);
for(i=1;i<=Lb_len;i++) {
GetElem(Lb,i,e);
if(!equal(en,e)) {
ListInsert(La,La_len,e); en=e;
}
}
}
对线性表中的元素已经进行了排序
时间复杂度:
控制结构:for循环
基本操作:GetElem(Lb,i,e)
顺序映象时 时间复杂度为O(n)
链式映象时 时间复杂度为O(n^2)
尽量对其进行排序
void MergeList(List La,List Lb,List &Lc) {
InitList(Lc);
i=j=1; k=0;
La_len=ListLength(La); Lb_len=ListLength(Lb);
while((i<=La_len)&&(j<=Lb_len)) {
GetElem(La,i,ai); GetElem(Lb,j,bj);
if(ai<=bj) {
ListInsert(Lc,++k,ai); ++i;
}
else {ListInsert(Lc,++k,bj); ++j;}
}
}
时间复杂度:
控制结构:三个并列的while循环
基本操作:LisstInsert(Lc,++k,e)
顺序映象时 时间复杂度为O(两表长之和)
链式映象时 时间复杂度为O(两表长和的平方)
单链表实现线性表的操作存在的问题:
1.表长是一个隐含的值
2.在最后一个元素最后插入元素时需遍历整个链表
3.在链表中,元素的“位序”概念淡化,结点的位置“概念”强化
改进链表的位置:
1.增加“表长”、“表尾指针”、“当前位置的指针”
2.基本操作由“位序”改为“指针”
一个带头结点的线性链表类型
typedef struct LNode { // 结点类型
ElemType data;
struct LNode *next;
} *Link,*Position;
Status MakeNode(Link &p,ElemType e);
// 分配由p指向的值为e的结点,并返回OK;若分配失败则返回ERROR
void FreeNode(Link &p);
// 释放p所指结点
typedef struct { // 链表类型
Link head,tail; // 分别指向线性链表中的头结点和最后一个结点
int len; // 指示线性链表中数据元素的个数
} LinkList;
链表的基本操作:
{结构初始化和销毁结构}
Status InitList(LinkList &L);
// 构造一个空的线性链表L
Status DestroyList(LinkList &L);
// 销毁线性链表L,L不再存在
{引用型操作}
Status ListEmpty(LinkList L);
// 判表空
int ListLength(Link L);
// 求表长
Status Prior(LinkList L);
// 改变当前指针指向其前驱
Status Next(LinkList L);
// 改变当前指针指向其后继
ElemType GetCrElem(LinkList L);
// 返回当前指针所指数据元素
Status LocatePos(LinkList L,int i);
// 改变当前指针指向第i个结点
Status LocateElem(LinkList L,ElemType e,Status (*compare)(ElemType,ElemType));
// 若存在与e满足函数compare()判定关系的元素,则移动当前指针指向期一个满足条件的元素,并返回OK;否则返回ERROR
Status ListTraverse(LinkList L,Status (*visit)());
// 依次对L的每个元素调用函数visit()
{加工型操作}
Status ClearList(LinkList &L);
// 重置为空表
Status SetCurElem(LinkList& L,ElemType e);
// 更新当前指针所指数据元素
Status Append(LinkList &L,Link s);
// 一串结点链接在最后一个结点之后
Status InsAfter(LinkList &L,ElemType e);
// 将元素e插在当前指针之后
Status DelAfter(LinkList &L,ElemType *e);
// 删除当前指针之后的结点
利用上述定义可以完成线性表的其他操作
比如ListInsert_L、MergeList_L等