标签:sequence 操作 基本 密度 clock 之间 改进 而且 内存
顺序表与链表是非常基本的数据结构,它们可以被统称为线性表。
线性表(Linear List)是由 n(n≥0)个数据元素(结点)a[0],a[1],a[2]…,a[n-1] 组成的有限序列。
顺序表和链表,是线性表的不同存储结构。它们各自有不同的特点和适用范围。针对它们各自的缺点,也有很多改进的措施。
顺序表一般表现为数组,使用一组地址连续的存储单元依次存储数据元素,如图 1 所示。它具有如下特点:
#include <string.h>
struct sqlist {
int *items, size, capacity;
sqlist():size(0), capacity(4) {
// initial capacity = 4
items = new int[capacity];
}
void doubleCapacity() {
capacity *= 2;
int* newItems = new int[capacity];
memcpy(newItems, items, sizeof(int)*size);
delete[] items;
items = newItems;
}
void add(int value) {
if (size >= capacity) {
doubleCapacity();
}
items[size++] = value;
}
};
这个办法不可避免的会浪费一些内存,因为数组的容量总是倍增的。而且每次扩容的时候,都需要将旧的数据全部复制一份,肯定会影响效率。不过实际上,这样做还是直接使用链表的效率要高,具体原因会在下一节进行分析。
链表,类似它的名字,表中的每个节点都保存有指向下一个节点的指针,所有节点串成一条链。根据指针的不同,还有单链表、双链表和循环链表的区分,如图 2 所示。
#include <stdio.h>
#include <time.h>
struct node {
int value;
node *next;
};
struct llist {
node *head;
void add(int value) {
node *newNode = new node();
newNode->value = value;
newNode->next = head;
head = newNode;
}
};
int main() {
int size = 100000;
sqlist list1;
llist list2;
long start = clock();
for (int i = 0;i < size;i++) {
list1.add(i);
}
long end = clock();
printf("sequence list: %d\n", end - start);
start = clock();
for (int i = 0;i < size;i++) {
list2.add(i);
}
end = clock();
printf("linked list: %d\n", end - start);
return 0;
}
在我的电脑上,链表的耗时大约是顺序表的 4~8 倍。会这样,是因为数组只需要很少的几次大块内存分配,而链表则需要很多次小块内存分配,内存分配操作相对是比较慢的,因而大大拖慢了链表的速度。这也是为什么会出现内存池。
因此,链表并不像理论分析的那样美好,在实际应用中要受很多条件制约,一般情况下还是安心用顺序表的好。
标签:sequence 操作 基本 密度 clock 之间 改进 而且 内存
原文地址:https://www.cnblogs.com/treasure716/p/9852774.html