数据结构第三章

线性表的基本运算在单链表上的实现:

  1. 初始化 空表由一个头指针和一个头结点组成
LinkList InitiateLinkList()
//建立一个空的单链表
{
 LinkList head;   //头指针
 head=malloc(sizeof(Node));//动态构建-结点,它是头结点
 head->next=NULL;
 return head
}

在算法中,变量head是链表的头指针,它指向创建的节点,即头结点.一个空链表禁有一个头结点,它的指针域为NULL.
2.求表长
在单链表储存结构中,线性表的表长等于单量表等于单链表中元素的节点个数,即除了头结点外的结点的个数.
设置一个工作指针p,初始时,p指向头结点,并设置一个计数器cnt,初值设置为0.然后,让工作指针p通过指针域逐个结点向尾结点移动,工作指针每向尾部移动一个结点,让计数器加1,直到工作指正p->next=null时,说明已经走到表的尾部,这时已完成对所有结点的访问,计数器cut的值即是表的长度.
3.读表元素
通常给定一个序号i,查找线性表的第i个元素.在链表中,任何相邻的两个节点通过一个指针相连,一个结点的位置包含在直接前驱结点的next域中,所以,必须从头指针出发,一直往后移动,直到第i个结点.
4.定位
线性表的定位运算,就是给定表元素的值,找出这个元素的位置.在单链表的实现中,则是给定一个结点的值,找出这个结点是单链表的第几个结点.定位运算又称作按值查找.在定位运算中,也需要重头到尾访问链表,直至找到需要的节点,返回其序号.若未找到,返回0.

int locateLinklist(LinkList head,DataType x)
{
 Node*p=head; //p是工作指针
 p=p->next;  //初始时 p指向首结点
 int i=0;    //i代表结点的序号,这里置初始值为0;
 while(p!=NULL&&p->data!=x)//访问链表
 {
  i++;
  p=p->next;
}
if(p!=NULL) return i+1;
else return 0
}

5.插入:单链表的插入运算是将给定值为x的元素插入到链表head的第i个结点之前.
a. 先找到单链表的的第i-1个结点q.
b.生成一个值为x的新结点p,p的指针域指向q的直接后继结点,如下图
c.q的指针域指向p
在这里插入图片描述

void inserLinklist (LinkList head,DataType x,int i)
// 在表head的第i个元素结点之前插入一个以x为值得新节点
{ 
 Node *p,*q;
 if(i==1) q=head;
 else q=GetLinklist(head,i-1);
 if(q==NULL)
 exit("找不到插入的位置");
 else {
 p=molloc(sizeof(Node));p->data=x; //生成新节点
 p->next=q->next;                  //新结点链域指向*q的后继结点
 q->next=p;                        //修改*q的链域
 }
}

注意:链接操作 p->next=q->next和q->next=p两条语句的执行顺序不能颠倒,否则结点*q的链域值(即指向原链表第i个结点的指针)将丢失.
6.删除:删除运算是给定一个值i,将链表中第i个结点从链表中移出,并修改相关结点的指针域,以维持剩余结点的链接关系,将ai结点移出后,需要修改该结点的直接前驱结点的指针域,使其指向移出结点的ai的直接后继结点.

void deleteLinklist(LinkList head,int i)
//删除表head 的第i个结点
{
 Node *q;
 if(i==1) q=head;
 else q=GetLinklist(head,i-1); //先找待删除结点的直接前驱
 if(q!=NUll&&q->next!-NULL)
 {
  p=q->next;//p指向待删除结点
  q->next=p->next; //移出待删结点
  free(p);      //释放已移出的结点p的空间
  
 }
 else exit("找不到要删除的节点"); //节点不存在
}

注意:free§是必不可少的,因为当一个结点从链表移出后,如果不释放它的空间,它将变成一个无用的结点,它会一直占用着系统内存空间,其他程序将无法使用这块空间.

7.双向循环链表:在单链表中的每个结点再设置一个指向其前驱的结点的指针域prior,这样每个结点有两个指针,其结构如图:

priordatanext

prior与next类型相同,它指向直接前驱结点.头结点的prior指向最后一个结点,最后一个结点的next指向头结点,由这种结点构成的链表称为双向循环链表,
在这里插入图片描述
设置p指向待删结点,删除p可通过下述语句完成:
1)p->prior->next=p->next; //p钱驱结点的后链指向p的后继结点
2)p->next->prior=p->prior; //p后继结点的前链指向p的前驱结点
3)free§; // 释放
p的空间
注意:(1) (1)的顺序可以颠倒

8.插入 在p所指向的结点的后面插入一个新结点*t,需要修改4个指针:
1)t-prior=p;
2)t->next=p->next;
3)p->next->prior=t;
4)p->next=t;
在这里插入图片描述
9.线性表和链表的时间性能和空间性能进行比较

  1. 对于按位置查找顺序表是随机存取,时间复杂度为O(1).单链表需要对表元素进行扫描,它时间复杂度为O(n).
    2)对于定位运算,基于操作是比较,顺序表和单链表上的实现算法的的时间复杂度是相同的O(n)
    3)对于插入,删除运算,在顺序表中,平均时间复杂度为O(n).在单链表中,其平均时间复杂度仍然为O(n)

10.线性表和链表的优缺点
1)单链表的每个结点包括数据域与指针域,指针需要占用额外的空间.
2)从整体考虑,顺序表要分配存储空间,如果预分配得过大,将造成浪费,若分配过小,又将发生上溢;单链表不需要预分配空间,只要空间内存没有耗尽,单链表中的结点个数就没有限制.

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

web修理工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值