跳转至

AB19-链表结点基础综合应用

## 对带头结点的正整数单链表执行特定操作: ## * 1. 找出最小值结点(非最后一个且唯一) ## * 2. 若该数值是奇数,将其与后继结点交换 ## * 3. 若该数值是偶数,则删除其后继结点

代码实现

C
/**
 * 对带头结点的正整数单链表执行特定操作:
 * 1. 找出最小值结点(非最后一个且唯一)
 * 2. 若该数值是奇数,将其与后继结点交换
 * 3. 若该数值是偶数,则删除其后继结点
 * @param L 指向链表头结点的指针
 * @return 操作成功返回true,无法操作返回false
 */
bool func(LinkList L) {
    // 边界条件检查:空链表或结点数少于2个
    if (L == NULL || L->next == NULL || L->next->next == NULL) {
        return false;
    }

    // p指向当前结点的前驱(从头结点开始)
    LNode* p = L;

    // pos指向最小值结点的前驱结点
    LNode* pos = L;

    // 遍历链表查找最小值结点
    while (p->next != NULL) {
        // 如果当前结点的值小于已知最小值
        if (p->next->data < pos->next->data) {
            pos = p;  // 更新最小值结点的前驱
        }
        p = p->next;  // 继续向后查找
    }

    // 检查最小值结点是否为最后一个结点
    if (pos->next->next == NULL) {
        return false;  // 最小值结点是最后一个,无法操作
    }

    // 获取最小值结点u和其后继结点r
    LNode* u = pos->next;    // 最小值结点
    LNode* r = u->next;      // 最小值结点的后继

    // 断开最小值结点与其后继的连接
    u->next = r->next;

    // 根据最小值的奇偶性执行不同操作
    if (pos->next->data % 2 == 0) {
        // 最小值是偶数:删除后继结点r
        free(r);
    } else {
        // 最小值是奇数:将后继结点r与最小值结点u交换位置
        r->next = pos->next;   // r指向u
        pos->next = r;         // pos指向r(r在前,u在后)
    }

    return true;  // 操作成功
}

算法执行流程图解

奇数情况示例:

Text Only
原链表:L→[ ]→[5]→[3]→[8]→[2]→[7]→NULL

查找最小值:
找到最小值3(位置pos指向[5])

操作前:L→[ ]→[5]→[3]→[8]→[2]→[7]→NULL
              ↑    ↑    ↑
             pos   u    r

操作步骤:
1. u->next = r->next  → [3]→[2]
2. 最小值3是奇数
3. r->next = u        → [8]→[3]
4. pos->next = r      → [5]→[8]

操作后:L→[ ]→[5]→[8]→[3]→[2]→[7]→NULL

偶数情况示例:

Text Only
原链表:L→[ ]→[5]→[4]→[8]→[2]→[7]→NULL

查找最小值:
找到最小值4(位置pos指向[5])

操作前:L→[ ]→[5]→[4]→[8]→[2]→[7]→NULL
              ↑    ↑    ↑
             pos   u    r

操作步骤:
1. u->next = r->next  → [4]→[2]
2. 最小值4是偶数
3. 删除结点r=[8]
4. free(r)

操作后:L→[ ]→[5]→[4]→[2]→[7]→NULL

操作详细图解

奇数交换操作:

Text Only
操作前:
L→[ ]→[A]→[奇数]→[B]→[C]→NULL
     ↑        ↑     ↑
    pos      u     r

步骤1:断开连接
L→[ ]→[A]→[奇数]→[C]→NULL    [B]→[C]→NULL
     ↑        ↑              ↑
    pos      u              r

步骤2:交换位置
L→[ ]→[A]→[B]→[奇数]→[C]→NULL
     ↑     ↑        ↑
    pos    r       u

偶数删除操作:

Text Only
操作前:
L→[ ]→[A]→[偶数]→[B]→[C]→NULL
     ↑        ↑     ↑
    pos      u     r

步骤1:断开连接
L→[ ]→[A]→[偶数]→[C]→NULL    [B]→[C]→NULL
     ↑        ↑              ↑
    pos      u              r

步骤2:删除r
L→[ ]→[A]→[偶数]→[C]→NULL

复杂度分析

时间复杂度:O(n)

  • 查找时间:需要遍历整个链表一次,O(n)
  • 操作时间:常数时间O(1)
  • 总体时间复杂度O(n)

空间复杂度:O(1)

  • 额外空间:只使用了常数个指针变量:pposur
  • 无辅助空间:没有使用额外的数据结构
  • 算法额外空间复杂度O(1)

优化版本:添加边界检查和更清晰的逻辑

C
/**
 * 优化版本:添加边界检查和更清晰的逻辑
 */
bool func_Optimized(LinkList L) {
    // 边界检查:确保至少有3个结点(头结点+2个数据结点)
    if (!L || !L->next || !L->next->next) {
        return false;
    }

    // 查找最小值结点的前驱
    LinkList current = L;
    LinkList min_prev = L;

    while (current->next) {
        if (current->next->data < min_prev->next->data) {
            min_prev = current;
        }
        current = current->next;
    }

    // 检查最小值结点是否为最后一个
    if (!min_prev->next->next) {
        return false;
    }

    // 获取相关结点
    LinkList min_node = min_prev->next;
    LinkList next_node = min_node->next;

    // 断开连接
    min_node->next = next_node->next;

    // 根据奇偶性执行操作
    if (min_node->data % 2 == 0) {
        // 偶数:删除后继结点
        free(next_node);
    } else {
        // 奇数:交换结点位置
        next_node->next = min_node;
        min_prev->next = next_node;
    }

    return true;
}

算法特点

核心思想: 1. 查找最小值:遍历链表找到最小值结点 2. 边界检查:确保最小值结点不是最后一个 3. 分类操作:根据最小值的奇偶性执行不同操作

关键操作: - 奇数操作:结点交换(不是数据交换) - 偶数操作:删除后继结点 - 通用操作:断开最小值结点与其后继的连接

创新点: - 结合了查找、判断、分类操作的综合性算法 - 区分结点交换和数据交换的概念 - 根据数值特性执行不同链表操作

应用场景: - 数据预处理和清洗 - 基于数值特性的链表结构调整 - 复合条件的链表操作

这种算法体现了链表操作的灵活性和复杂性,是数据结构与算法设计中的经典案例。