学习完顺序表和链表,那我们在日后的实际算法选择中,到底如何去做选择呢?
我们从四个方式来对顺序表和链表作比较。分别是:① 存取方式、② 逻辑结构和物理结构、③ 基本操作、④ 内存空间。
-
存取方式
-
顺序表:可以实现顺序存取和随机存取
-
单链表:只能实现顺序存取
-
-
逻辑结构和物理结构
-
顺序表:逻辑相邻物理上也相邻,通过相邻表示逻辑关系
-
单链表:逻辑相邻物理上不一定相邻,通过指针表示逻辑关系
-
-
基本操作(时间复杂度)
-
插入 & 删除
-
顺序表:O(n),且需要大量移动元素
-
单链表:O(1)(结点指针已知);O(n)(结点指针未知)
-
-
按值查找
-
顺序表:O(n),遍历查找
-
单链表:O(n),遍历查找
-
-
按序号查找
-
顺序表:O(1),直接得到内存地址
-
单链表:O(n),遍历层层查找
-
-
-
内存空间
-
顺序存储:无论静态分配还是非静态(动态)分配都需要预先分配合适的内存空间
-
静态分配时预分配空间太大会造成浪费,太小会造成溢出
-
动态分配时虽不会溢出但是扩充空间需要大量移动元素,操作效率低
-
-
链式存储:在需要时分配结点空间即可,高效方便,但每个结点指针都需要额外的空间
-
-
那在不同的情况下,顺序表和单链表我们如何去做选择?
顺序表 单链表 规模难估计 √ 存储密度 √ 按序号访问 √ 插入和删除 √ 基于数组 √ 基于指针 √
我们在顺序表与链表的三个常用操作中去实现其具体的算法。分别是:求最值、逆置、归并。
-
求最值及逆置——数据:
L = (3, 1, 5, 9, 2)
-
求最值
-
顺序表:
int min = L[0]; int max = L[0]; for(int i=0; i<n; i++) { if(min > L[i]) min = L[i]; if(max < L[i]) max = L[i]; }
时间复杂度:O(n)
-
单链表(含头结点,不特殊说明均含头结点):
int min = p->next->data; int max = p->next->data; for(; p!=NULL; p=p->next) { if(min > p->data) min = p->data; if(max < p->data) max = p->data; } /* // while 实现 while(p != NULL) { if(min > p->data) min = p->data; if(max < p->data) max = p->data; p = p->next; } */
时间复杂度:O(n)
-
-
逆置
-
顺序表:
int i = 0; int j = n-1; while(i < j) { int temp = L[i]; L[i] = L[j]; L[j] = temp; }
时间复杂度:O(n)
-
单链表:
// 找到尾结点指针 r LNode *r; while(r->next) { r = r->next; } // 将头结点后每次第一个结点放到尾结点 LNode *p; while(p->next != r) { int *temp = p->next; p->next = temp->next; temp->next = r->next; r->next = temp; }
时间复杂度:O(n)
-
-
归并
-
输入:
L1=(1, 2, 3, 5)
、L2=(4, 6, 7, 8)
-
输出:
L=(1, 2, 3, 4, 5, 6, 7, 8)
-
顺序表:
int i=0, j=0; // L1 和 L2 数组下标 int k=0; // 新生成数组下标 for(; i<L1_Length && j<L2_Length; k++) { if(L1[i] < L2[j]) L[k] = L1[i++]; else L[k] = L2[j++]; } while(i < L1_Length) L[k++] = L1[i++]; while(i < L2_Length) L[k++] = L1[j++];
时间复杂度:O(n),这里的 n 是指两个数组的元素个数之和
-
单链表:
// L 头结点为 r while(p->next != NULL && q->next != NULL) { if(p->next->data < q->next->data) { r->next = p->next; p->next = p->next->next; } else { r->next = q->next; q->next = q->next->next; } r = r->next; } if(p->next != NULL) r->next = p->next; if(q->next != NULL) r->next = q->next; free(p); free(q);
时间复杂度:O(n),这里的 n 是指两个链表的元素个数之和
-
xxx
-
xxxx( )
A. xxx
B. XX
C. Xx
D. xX查看解析
答案:x