线性数据结构 数组 动态数组 链表

引言

线性数据结构主要是数组,还有可以优化数组的动态数组链表

动态数组:数组在声明是需要指定长度,并且不能存储超过此长度的元素。为了解决这个问题设计的数据结构就是动态数组,其长度能够根据元素个数变化。

动态数组不是数组,而是依据数组设计出来的一种数据结构,其继承了数组的以下特性:

(1)元素保存于连续的内存空间。
(2)返回或更改指定位置的元素,可以在O(1)时间内完成。

此外,动态数组还有数组不具备的特点:

(1)可以进行变更数组长度的resize()运算,此运算需要耗费数组长度N的运算时间。
(2)通过append()运算可以将给定元素添加到数组末尾,以增加1个数组的空间,此运算耗费常数运算时间。

为实现这些运算,动态数组使用动态分配的数组:

int size;	//数组大小
Elementype* array;	//指向实际数组的指针 

分配新数组并将原数据复制到新数组时,耗费的时间会正比于数组长度N。这就可以满足“在O(n)时间里变更数组长度的**resize()**运算”

我们将已分配的内存空间称为数组容量,实际元素个数称为数组大小,当数组大小小于数组容量时,使用**append()**运算可将size+1,然后向增加位置写入新值即可解决问题:

//append(newValue)的部分代码
array[size++] = newValue;

如果数组容量已满,就需要先分配更大的内存空间,类似resize()运算:

//数组容量已满,则重新分配内存空间
if(size == capacity){
	//重新分配容量增加M的新数组
	int newCapacity = capacity + M;
	int* newArray = new int[newCapacity];
	//复制原数组数据
	for(int i=0;i<size;++i)
	 newArray[i] = array[i];
	//删除原数组,代之以新数组;
	if(array) delete [] array;
	array = newArray;
	capacity = newcapacity; 
}
//在数组末端添加元素
array[size++] = newValue; 

动态数组的重新分配策略:在常数时间内完成append()运算的秘诀不在于每次重新分配时保留固定数量的冗余空间,而需要保留与当前元素个数成比例的冗余空间。例如一开始容量为1,满了就增加到2,再满了就增加到4,8,16…这样就可以将一次append()运算时间视为O(1)。

标准库的动态数组实现方法:C++中的vector,其内部使用数组,几乎具有和静态数组相同的速度。如果要多次指向append()运算,如果知道最终数组的大小,可以预先设定数组大小,可以节省时间。

链表:保持数组元素顺序不变的前提下,向数组任意位置插入新元素或删除任意位置元素的操作会耗费大量时间,为解决这个问题设计的数据结构就是链表,链表可以在常数时间内完成向任意位置插入和删除元素的操作。

数组的元素保存于连续的内存空间,链表元素会保存在离散的内存空间,使用指针指向前后的元素,前面的元素叫做头节点,后面的元素叫做尾结点,链表基本由拥有指向头节点和尾结点指针的类实现。

struct ListNode{
	int element;	//保存的元素
	ListNode *prev, *next;	//指向前一结点和下一节点的指针 
}; 

使用链表:想要在链表中找出第i个结点,只能从头逐个查找,耗时会与链表长度成正比。但保持各节点顺序的前提下,删除和插入新节点则非常简单,只需改变两边指针即可。基于链表的这种特性,解决实际问题时常和动态数组互为补充。

标准库中链表的实现方法:C++STL中的list就是这种数据结构。

链表应用

(1)拼接运算,C++STL中的list通过splice()成员函数实现拼接运算。
(2)撤销删除元素的操作,知道已删除节点node的相关信息,就可以进行逆向恢复的操作。

//变更node前后结点的指针,从链表中删除node
void deleteNode(ListNode* node){
	node->prev->next = node->next;
	node->next->prev = node->prev;
} 
//变更node前后结点的指针,将其重新插入链表
void recoverNode(ListNode* node){
	node->prev->next = node;
	node->next->prev = node;
} 

动态数组和链表的比较

运算动态数组链表
查找前/后元素O(1)O(1)
在末端插入/删除元素O(1)O(1)
在末端以外的位置插入/ 删除元素O(n)O(1)
查找任意位置的元素O(1)O(n)
求大小O(1)O(n)或根据实现方法O(1)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

三元湖有大锦鲤

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

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

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

打赏作者

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

抵扣说明:

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

余额充值