线性表定义
- 相同数据类型->每个数据元素占用空间一样大; 有限序列->有次序
顺序表
- 按位查找,时间复杂度O(1)
- 优点:可随机存取,存储密度高
- 缺点:要求大片连续空间,改变容量不方便
错题
- 若线性表最常用的操作是存取第i个元素及其前驱和后继元素的值,为了提高效率,应采用(D)的存储方式。
- A.单链表;B.双向链表;C.单循环链表;D.顺序表
- 解释:ABC都只能从头结点依次顺序查找,时间复杂度为O(n);只有顺序表可以按序号随机存取,时间复杂度为O(1)。
链表
- 优点:插入运算方便,删除运算方便
单链表
头插法的重要应用:链表的逆置。
错题
以下所有回答均为AI的答案,不知道对不对。
问:一个链表最常用的操作是在末尾插入结点和删除结点,则选用带头结点的双循环链表最节省时间,为啥带尾指针的单循环链表没有带头结点的双循环链表节省时间呀?
答:带头结点的双循环链表相对于带尾指针的单循环链表,确实在进行在末尾插入节点和删除节点的操作时更加高效。
首先,让我们回顾一下两种链表的定义:
- 带头结点的双循环链表:在链表的头部额外添加一个头结点,它的
next指针指向链表的第一个元素,而链表的最后一个元素的next指针则指向头结点。 - 带尾指针的单循环链表:链表的最后一个元素的
next指针不再指向nullptr,而是指向链表的头部。
现在来看一下在末尾插入节点和删除节点的操作的时间复杂度:
在带头结点的双循环链表中:
- 在末尾插入节点的时间复杂度为O(1),因为只需要修改头结点和最后一个节点的指针即可。
- 删除节点的时间复杂度也为O(1),因为我们可以通过找到要删除的节点的前一个节点,然后修改指针来删除节点。
在带尾指针的单循环链表中:
- 在末尾插入节点的时间复杂度为O(1),因为只需要修改尾指针和新节点的指针即可。
- 删除节点的时间复杂度为O(n),因为需要遍历链表来找到要删除的节点的前一个节点,然后修改指针。
因此,带头结点的双循环链表在插入和删除节点的操作上更加高效,时间复杂度为O(1),而带尾指针的单循环链表在删除节点的操作上需要遍历链表,时间复杂度为O(n)。 在长度为n的有序单链表中插入一个新结点,并仍然保持有序的时间复杂度是?
问:在长度为n的有序单链表中插入一个新节点,并保持有序的时间复杂度为O(n),其中n是链表的长度。
答:要在有序链表中插入一个新节点,需要进行以下操作:
- 遍历链表找到插入位置的前一个节点。最坏情况下,需要遍历整个链表,时间复杂度为O(n)。
- 创建新节点并将其插入到合适的位置。这一步的时间复杂度为O(1)。
- 修改前一个节点的指针,将其指向新节点。也是O(1)的时间复杂度。
因此,总的时间复杂度为O(n)。即使链表已经有序,我们仍然需要遍历链表来找到插入位置,因此无法避免对整个链表的遍历。
问:某线性表用带头结点的循环单链表存储,头指针为head,当head->next->next==head成立时,线性表长度可能是0或1,为啥呀
答:当 head->next->next == head 成立时,说明链表中至少有一个节点,且该节点的下一个节点指针指向了头结点。这种情况下,线性表的长度可能是0或1。
具体情况如下:
- 如果只有头结点,即链表中没有其他节点,那么线性表的长度为0。
- 如果链表中除了头结点还有一个节点,那么线性表的长度为1。
因此,线性表的长度可能是0或1,具体取决于链表中是否存在除头结点外的其他节点
问:设对n(n>1)个元素的线性表运算只有四种,删除第一个元素;删除最后一个元素;在第一个元素之前插入新元素;在最后一个元素之后插入新元素,则最好使用
- A、只有尾结点指针没有头结点指针的循环单链表
- B、只有尾结点指针没有头结点指针的非循环双链表
- C、只有头结点指针没有尾结点指针的循环双链表
- D、既有头结点指针又有尾结点指针的循环单链表
A、只有尾结点指针没有头结点指针的循环单链表:
- 删除第一个元素:由于只有尾结点指针,可以通过尾结点的next指针找到第一个元素,并将其删除,时间复杂度为O(1)。
- 删除最后一个元素:由于只有尾结点指针,无法直接访问到最后一个元素,需要遍历整个链表找到倒数第二个节点并修改其next指针,时间复杂度为O(n)。
- 在第一个元素之前插入新元素:由于只有尾结点指针而没有头结点指针的循环单链表,不能在第一个元素之前插入新元素。这是因为在循环单链表中,尾结点的next指针指向第一个元素,而没有指向最后一个元素的指针。
- 在最后一个元素之后插入新元素:由于只有尾结点指针,无法直接访问到最后一个元素,需要遍历整个链表找到最后一个节点并修改其next指针,时间复杂度为O(n)。
B、只有尾结点指针没有头结点指针的非循环双链表:
- 删除第一个元素:由于只有尾结点指针,无法直接访问到头结点,因此删除第一个元素会变得复杂,需要遍历整个链表找到第二个节点并修改其prev和next指针,时间复杂度为O(n)。
- 删除最后一个元素:由于只有尾结点指针,可以直接访问到最后一个元素,并将其删除,时间复杂度为O(1)。
- 在第一个元素之前插入新元素:由于只有尾结点指针,无法直接访问到头结点,因此在第一个元素之前插入新元素会变得复杂,需要遍历整个链表找到第一个节点并修改其prev和next指针,时间复杂度为O(n)。
- 在最后一个元素之后插入新元素:由于只有尾结点指针,可以直接访问到最后一个元素,并将新元素插入到其后面,时间复杂度为O(1)。
C、只有头结点指针没有尾结点指针的循环双链表:
- 删除第一个元素:循环双链表可以直接通过头结点的next指针删除第一个元素,时间复杂度为O(1)。
- 删除最后一个元素:循环双链表可以直接通过尾结点的prev指针删除最后一个元素,时间复杂度为O(1)。
- 在第一个元素之前插入新元素:循环双链表可以通过头结点的next指针和新元素结点的prev指针完成插入操作,时间复杂度为O(1)。
- 在最后一个元素之后插入新元素:循环双链表可以通过尾结点的next指针和新元素结点的prev指针完成插入操作,时间复杂度为O(1)。
D、既有头结点指针又有尾结点指针的循环单链表:
- 删除第一个元素:在循环单链表中,删除第一个元素需要找到头结点的下一个节点,并修改头结点的next指针,时间复杂度为O(1)。D选项可以直接通过头结点的next指针进行操作。
- 删除最后一个元素:在循环单链表中,删除最后一个元素需要找到倒数第二个节点,并修改其next指针指向头结点,时间复杂度为O(n)。D选项可以通过尾结点的next指针进行操作,但需要额外的空间存储尾结点指针。
- 在第一个元素之前插入新元素:在循环单链表中,可以直接通过头结点进行在第一个元素之前插入新元素的操作,而不需要找到头结点的前一个节点,时间复杂度为O(1)。
- 在最后一个元素之后插入新元素:在循环单链表中,在最后一个元素之后插入新元素需要找到尾结点,并修改其next指针指向新元素,时间复杂度为O(1)。D选项可以直接通过尾结点的next指针进行操作。
问:给定有n个元素的一维数组,建立一个有序单链表的最低时间复杂度为?
答:更好的方法是使用归并排序(Merge Sort)算法来建立有序单链表。归并排序算法是一种基于分治的排序算法,其时间复杂度是O(nlog2n)。
具体操作如下:
- 将数组分成两个相等大小的子数组,分别递归地对它们进行排序。
- 将两个已排序的子数组合并成一个有序的单链表。
在归并排序的合并过程中,我们可以使用指针来遍历两个已排序的子链表,并按照大小顺序依次将元素连接起来。这个过程的时间复杂度是线性的,即O(n)。
因此,使用归并排序算法建立有序单链表的最低时间复杂度是O(nlog2n)。
问:在一个长度为n的带头结点的单链表h上,设有尾指针r,则执行什么操作与表长有关?
- A. 删除单链表中的第一个元素
- B. 删除单链表的最后一个元素
- C. 在单链表第一个元素前插入一个新元素
- D. 在单链表最后一个元素后插入一个新元素
答:B。由于我们拥有尾指针r,可以直接通过尾指针找到最后一个元素以及其前一个元素,从而实现删除最后一个元素的操作。而删除单链表的第一个元素或在单链表的第一个元素前插入一个新元素,不需要尾指针的参与,与表长无关。而D选项中,虽然是在链表的最后一个元素后插入一个新元素,但是由于有尾指针r的存在,我们可以直接通过尾指针找到最后一个元素,因此也不受表长的影响。