为什么单链表的插入和删除速度要比顺序表快

单链表与顺序表的问题探究


首先这是顺序表的插入和删除的代码:

//在顺序表L的第i个位置插入元素e
bool ListInsert(SqList &L,int i,ElemType e){
     if(i < 1 || i > L.length + 1) //判断i的范围是否有效 
     return false;
     if(L.length >= MaxSize) //当前存储空间已满,不能插入 
     return false;
     for(int j = L.length; j >= i; j--) //将第i个元素及以后元素后移 
        L.data[j] = L.data[j-1];
       L.data[i-1] = e;  //在第i个元素放入元素e 
	   L.length++;     //顺序表长度加1 
	   return true;
}
//删除顺序表L的第i个元素,并通过引用参数将值返回 
bool ListInsert(SqList &L,int i,ElemType &e){
     if(i < 1 || i > L.length) //判断i的范围是否有效 
     return false;
     e = L.data[i-1];   //将被删除的元素赋值给e 
     for(int j = i; j <= L.length - 1; j++) //将第i个位置后的元素前移 
        L.data[j-1] = L.data[j];
	   L.length--;
	   return true;
}

接着是单链表的插入删除代码:

//按序号查找单链表的第i个结点 
LNode *GetElem(LinkList L,int i){
	int j = 1;//计数,初值为1
	LNode *p = L->next; //头结点指针赋值给p
	if(i == 0)   
	return L; //若i等于0,则返回头结点
	if(i < 1)
	return NULL; //若i无效,则返回NULL
	while(p != NULL && j < i){ //从第一个结点开始找,查找第j个结点
	 p = p -> next;
	 j++; 
    }
    return p;   //返回第i个结点的指针,若i大于表长则返回NULL 
} 

//按序号插入单链表的第i个结点 
bool InsertElem(LinkList L,int i,ElemType e){
	LNode *p = GetElem(L,i - 1);   //查找插入位置的前驱结点 
	if(p == NULL) //若该结点为空,则插入失败 
	return false; 
	LNode *s = (Lode*)malloc(sizeof(LNode));  //创建新结点s 
	s->data = e;    //将新节点s的数据域赋值为e 
	s->next = p->next; //新节点s的后继指向p的后继结点
	p->next = s;  //p结点的后继指向新节点s
	return true; 
} 
//按序号删除单链表的第i个结点 
bool DeleteElem(LinkList L,int i,ElemType &e){
	LNode *p = GetElem(L,i - 1);   //查找删除位置的前驱结点 
	if(p == NULL) //若该结点为空,则插入失败 
	return false;  
	LNode *q = p->next; //q指向被删除结点 
	p->next = q->next; //将q结点从链中断开 
	free(q);   //释放结点的存储空间 
	return true; 
}

分析这两段代码,我们会发现不论是顺序表的插入删除操作,还是单链表的插入删除操作,时间复杂度均为O(n),空间复杂度均为O(1)。

但我们学过数据结构后,一定听说过这么一句话:“当涉及到大量的插入与删除操作时,用链表比用顺序表效率更高,效果更佳。”

可从时间复杂度和空间复杂度上来看,这两种方式的效果明明几乎是一样的啊…为什么用链表的方式来进行插入与删除操作,效率就会比顺序表要高呢?

这就涉及到计算机组成原理的知识了。。。

虽然顺序表和单链表插入与删除算法的时间复杂度均为O(n),但由于单链表的插入删除操作中,主要时间用于指针后移,寻找插入与删除的位置,在硬件层次上表现为CPU做加法运算

这个应该不难理解吧,C语言如果学过指针,都知道指针是指向一个内存单元的,那指针的移动,就相当于指针所指向的内存单元的变化,而内存单元的地址标号又是整数。所以从硬件角度上来看,指针的移动就相当于CPU对指针所指向的内存单元地址进行加法或减法运算。

在顺序表的操作中,主要的时间用于元素移动,元素的移动又是通过赋值操作实现的。因此在硬件层次上需要让CPU从Cache或主存中取数,读数,再进行运算操作,这显然是比用链表实现的速度更慢的

(如果还有疑问,我相信也许是这个疑问:指针的移动就不需要进行取数操作吗?

我的回答是:首先CPU是一条一条执行指令的,当前欲执行的指令从IR送入CPU后,CPU开始解析,当它解析指针时,可以直接就解析出一个地址,而直接对这个地址进行运算,因而相比顺序表中的赋值操作省去了去存储器内取数的时间)

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值