数组
-
类型相同的占用一块定长的连续内存空间的节点集合
-
常用算法:初始化、遍历输出、追加元素、插入元素、删除元素、排序、倒置等
-
可以通过下标计算出元素的物理地址,所以随机访问速度极快
-
新增和删除速度较慢,因为需要对后续元素移位
-
数组长度不可变,新增时如果长度不够则需要考虑在原数组后追加申请空间或创建一个新数组替代原来的数组
链表
-
类型相同的离散的彼此通过指针相连的节点集合
-
每个节点只有一个前驱节点和一个后续节点,首节点没有前驱节点,尾节点没有后续节点
-
常用算法:遍历、查找、清空、销毁、求长度、排序、删除节点、插入节点等
-
链表分为以下几种
-
单链表:普通的链表
-
双链表:每个节点有两个指针域,每个节点之间的指向都是双向的,除了头节点、首节点和尾节点
-
循环链表:可以通过任何一个节点找到其他所有的节点
-
-
随机访问速度较慢,需要从头节点开始依次访问
-
新增和删除速度较快,虽然也需要从头节点开始依次访问,但定位到元素后只需要改变指针的指向即可
数组和双向链表的比较
-
随机访问时数组的优势远远大于链表
-
有序数组使用二分法查找某个关键字效率也远远大于有序链表
-
虽然说链表新增删除较快,而数组较慢,但不是绝对的
- 数组需要对后续元素移位,这是最大的劣势;而链表需要先访问到指定节点才可以移动指针完成新增删除
- 对偏中部位置及之前元素进行新增删除时,数组需要对后续大量数据移位,而双向链表只需要前向访问较少元素即可完成新增删除
- 对偏中部位置及之后元素进行新增删除时,数组需要移位的数据和双向链表后向访问的数据量相同,效率差距不会很大
数组、链表各自实现选择排序
for(int i = 0; i < len-1; i++){
for(int j = i+1; j < len; j++){
if(arr[i] > arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
for(Node* pNodei = pHead->pNext; pNodei->pNext != NULL; pNodei = pNodei->pNext){
for(Node* pNodej = pNodei->pNext; pNodej != NULL; pNodej = pNodej->pNext){
if(pNodei->data > pNodej->data){
int temp = pNodei->data;
pNodei->data = pNodej->data;
pNodej->data = temp;
}
}
}
// 可以看出两种排序方式总体上,甚至在算法所有细节上的思路都是相同的,不同的就是表示方式不同