已知一个带头结点的单链表L存放n个元素,其中结点类型为(data,next),p指向其中某个结点。请设计一个平均时间复杂度为O(1)的算法删除结点p,并且说明你的算法的平均时间复杂度为O(1)。
思路
首先判断要删除的结点是否为空或者是否为头结点,如果是则无法删除,返回ERROR。如果要删除的结点不是尾节点,则将要删除结点的数据和下一个结点的数据进行交换,然后删除下一个结点,将要删除结点的指针指向下一个结点的下一个结点,最后释放下一个结点的内存空间。如果要删除的结点是尾节点,则需要遍历链表找到要删除结点的前驱结点,将其指针指向NULL,并释放要删除结点的内存空间。
平均时间复杂度为O(1),因为大部分情况下只需要进行一次数据交换和一次指针操作就能完成删除操作。空间复杂度为O(1),因为算法中只使用了常数个额外空间来进行结点数据的交换和指针操作,并没有随着输入规模的增加而增加。
AC代码
#include <algorithm>
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;
using Status = int;
using ElemType = int;
const int N = 1e6 + 7;
const int TRUE = 1;
const int FALSE = 0;
const int OK = 1;
const int ERROR = 0;
const int INFEASIBLE = -1;
const int OVERFLOW = -2;
int n;
ElemType a[N];
struct ListNode {
ElemType data;
ListNode *next;
};
using LinkedList = ListNode *;
Status initList(LinkedList &first) {
first = (ListNode *)malloc(sizeof(ListNode));
first->next = NULL;
return OK;
}
Status listInsert(LinkedList &L, int pos, ElemType e) {
ListNode *p = L;
for (int i = 0; p && i < pos; i++) {
p = p->next;
}
if (!p) {
return ERROR;
}
ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
newNode->data = e;
newNode->next = p->next;
p->next = newNode;
return OK;
}
ElemType getElem(LinkedList L, int pos) {
ListNode *p = L->next;
for (int i = 0; p && i < pos; i++) {
p = p->next;
}
if (!p) {
return NULL;
}
return p->data;
}
Status listErase(LinkedList L, ListNode *p) {
if (!p || p == L) {
// 不能删除头结点
return ERROR;
}
if (p->next) {
// 尾节点不适用
swap(p->data, p->next->data);
ListNode *t = p->next;
p->next = p->next->next;
free(t);
return OK;
}
ListNode *prior = L->next;
while (prior && prior->next != p) {
prior = prior->next;
}
if (!prior) {
return ERROR;
}
free(prior->next);
prior->next = NULL;
return OK;
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int k;
cin >> k;
LinkedList L;
initList(L);
for (int i = 0; i < n; i++) {
listInsert(L, i, a[i]);
}
for (int i = 0; i < n; i++) {
cout << getElem(L, i) << " ";
}
cout << "\n";
// n -= listErase(L, L);
// n -= listErase(L, L->next);
n -= listErase(L, L->next->next);
// n -= listErase(L, L->next->next->next->next->next->next);
for (int i = 0; i < n; i++) {
cout << getElem(L, i) << " ";
}
cout << "\n";
return 0;
}