【数据结构与算法分析——c语言描述Mark Allen Weiss 学习笔记】表的数组实现 链表

chap 1 引论

算法基本法则

  1. 基准情形
  2. 不断递进(向基准情形)
  3. 设计法则 假设所有递归调用都能运行
  4. 合成效益法则 求解一个问题同一实例避免重复性工作

chap3 表 栈 队列

3.1 抽象数据类型(ADT)

3.2表ADT

  • 后继 前驱
  • 可能的几个运算
    printList MakeEmpty Find Insert Delete

表——数组实现

运算是否容易实现具体实现方法
PrintListYesfor遍历
MakeEmptyYesfor遍历 or strcpy
Find查找算法
Next/previous查找算法
Insertno后移其后所有元素
Deleteno前移其后所有元素

链表

  • 不连续储存

  • Insert Delete实现
    在这里插入图片描述

  • 细节

    • 表头增删有问题
      • 考虑添加一个虚拟的,而不属于待处理数组的表头
      • 编写function:FindPrevious以判断前驱节点,当检测为 A 1 A_1 A1时返回表头header地址
        在这里插入图片描述
  • 表ADT代码实现

    • ADT的声明
/*头文件.h中*/ //作为类型的List(表)和Postion(位置)、各函数名写在其中
#ifndef _List_H
struct Node;           //声明结点结构体类型
typedef struct Node *PtrToNode;//声明节点指针类型
typedef PtrToNode List;//声明指针表(以表头地址表示)的类型
typedef PtrTonode position;//声明 节点地址的类型

List MakeEmpty(List L);
int IsEmpty(List L);
int IsLast(Postion P,List L)
Postion Find(ElementType X,List L);
void Delete(ElementType X,List L);
Position FindPrevious(ElementType X,List L);
void Insert(ElementType X,List L,Position P);
void DeleteList(List L);
position Header(List L);  //找到(虚拟)表头A_0
Position First(List L);  //找到第一个元素A_1
Position First(List L);
ElementType Retrieve(position P);//检索(给地址找出元素)
#endif /*_List_H*/

/*源文件.c*中*/ //具体的Node声明则在这里
struct Node
{
  ElementType Element;
  Position Next;
}

这里用不同名字细分PtrToNode非常值得学习
不局限于实质一样就叫一个名字

  • 具体函数实现
//判断是否是空表
/* Return true if L is empty*/
int IsEmpty(list L)
{
  return L->Next==NULL;//如果判等则为真返回1;
}
//判断是否是表末元素
//Return true if P is the last position in list L
//Parameter L is unused in this implementation
int 
Islast(Postion P,List L)
{
  return P->Next==NULL;
}
//Find 例程
//Return Postion of X in L;NULL if not found
Positon
Find(ElementType X,List L)
{
  Positon P;
  P=L->Next;//P初始为A_1的地址
  while(P!=NULL && P->Element!=X)
    p=p->Next;
  return P;
}
//Delete 例程
//看图3-3
//Delete first occurrence of X form a list
void
Delete(ElementType X,List L)
{
  Position P,TmpCell;
  P=FindPrevious(X,L);
  if(!IsLast(X,L))
  {
    TmpCell=P->Next;      //TmpCell此时指向X
    p->Next=tmpCell->Next;//TmpCell->指向X后面一个元素
  }
}

//其中FindPrevious实现
//遍历直到地址为P->Next的元素P->Next->Element为X,则此时P即为所求
//如果是空表则返回表头A_0;
//如果没有找到X(最后一个元素LastNode->Next=NULL则跳出while,末尾元素地址;
Positon
FindPrevious(ElementType X,List L)
{
  Position P;
  P=L;                                       //P从表头开始
  while(P->Next!=NULL&&P->Next->Element!=X)  
    P=P->Next;                             
  return P;
}
//Insert  例程
//看图3-4
//将新元素插入到A_p之后
//Parameter L is unused in this implementation
void
Insert(Element X,List L,Position P)
{
  Position TmpCell;
  TmpCell=malloc(sizeof(struct Node));  
  if(TmpCell==NULL)
    FatalError("Out of space!");        //申请内存,内存不够了报警
  
  TmpCell->Element=x;
  TmpCell->Next=P->Next;
  P->Next=TmpCell;
}

上述插入Insert亦可以用于实现链表创建。
可以注意到,每次增加一个元素,通过调用malloc向系统申请一个随机位置得到一个节点Node需要的内存,这个malloc申请的内存并不是临时的,而是将来这个链表对应的节点长期使用的。
区分Delete每次调用都应当有一个free内存的过程,否则删除之后永久占用

void
DeleteList(List L)
{
  Positon P,Tmp;
  
  P=L->Next;
  L->Next=NULL; //让表头直接移开
  //但是肯定要把占用内存清理了,目前P指向A_1,我们依次删除
  while(P!=NULL)
  {
    Tmp=P->Next;  //删之前记录下下一个结点地址
    free(p);      //打扫干净这个结点
    //对应的malloc是在创建表的时候的每个元素对应的Insert里头的malloc
    P=tmp;        //接下来打扫下一个结点
  }
}
  • 双链表循环链表
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值