2.3.7, 3
4
- 经典递归,出口依旧是空结点
- 利用递归栈反向输出结点值
- 时间复杂度O(n),空间复杂度O(n)
void reversePrintList(LinkList L) { if (L == NULL) return; reversePrintList(L->next); cout << L->data << " "; } 复制代码
- 从头到尾遍历整个链表,用栈存储每个结点的值再输出即可
- 时间复杂度O(n),空间复杂度O(n)
void reversePrintList2(LinkList L) { if (L == NULL) return; // 1.遍历存储 stack<int> stack; while (L != NULL) { stack.push(L->data); L = L->next; } // 2.输出 while (!stack.empty()) { cout << stack.top() << " "; stack.pop(); } } 复制代码
2.3.7, 4
- 跟顺序表找最小值基本没差,只是需要加一个指针指向前缀便于删除
- 定义双指针:p和前缀pre,同时定义minp和minpre指向当前最小结点
- 时间复杂度O(n),空间复杂度O(1)
void delMin(LinkList &L) { // 1.定义指针 LNode *pre = L, *p = pre->next; LNode *minpre = pre, *minp = p; // 2.找到最小值 while (p != NULL) { if (p->data < minp->data) { minpre = pre; minp = p; } pre = p; p = p->next; } // 3.删除最小值 minpre->next = minp->next; free(minp); } 复制代码
2.3.7, 5
- 就地逆置,对于带头结点的链表来说就是把头结点之后的结点按照头插法再插入
- 还是双指针,这次需要p以及p的后缀(画图更容易理解)
- 头插也就是说每次都把新的p插入到L后面!这样L依旧是头结点,不需要返回新的链表
- 时间复杂度O(n),空间复杂度O(1)
void reverse(LinkList &L) { LNode *p = L->next, *q; L->next = NULL; while (p != NULL) { q = p->next; // 记录后缀 p->next = L->next; // 插到L后面 L->next = p; p = q; // 继续插入下一个结点 } }