6-6 带头结点的链式表操作集 (20 分)

题目地址:https://pintia.cn/problem-sets/15/problems/729

头节点创建但并不储存信息,操作与普通链式表基本相同

List MakeEmpty() {
    List L = (List)malloc(sizeof(struct LNode));
    L ->Next = NULL;
    return L;
}

Position Find(List L, ElementType X) {
    List q = L;
    while(q) {
        if(q->Data == X) return q;
        q = q->Next;
    }
    return ERROR;
}

bool Insert(List L, ElementType X, Position P) {
    if(P == L->Next) {
        List p = (List)malloc(sizeof(struct LNode));
        p->Data = X;
        p->Next = L->Next;
        L->Next = p;
        return true;
    }

    List p = L;
    while(p) {
        if(p->Next == P) {
            List q = (List)malloc(sizeof(struct LNode));
            q->Data = X;
            q->Next = P;
            p->Next = q;
            return true;
        }
        p = p->Next;
    }
    printf("Wrong Position for Insertion\n");
    return false;
}

bool Delete(List L, Position P) {
    List q = L;
    while(q) {
        if(q->Next == P) {
            q->Next = P->Next;
            return true;
        }
        q = q->Next;
    }
    printf("Wrong Position for Deletion\n");
    return false;
}
View Code

 

转载于:https://www.cnblogs.com/mile-star/p/11458151.html

<think>嗯,用户想了解带头结点的单链常见操作汇总,包括数据结构和实现方法。首先,我需要回忆带头节点单链的特点。带头节点的链有一个不存储数据的头结点,作为起始点,这样操作起来更方便,比如插入和删除时不需要特别处理头结点的情况。根据引用[5],结构体定义包括数据域和指向下一个节点的指针,比如typedef struct Node { ELEM_TYPE mdata; struct Node* pnext; } Node, *Link;。 接下来,我需要整理常见的操作。首先是初始化。初始化时需要创建头结点,并让它的next指针指向NULL。然后考虑插入操作,包括头插法和尾插法。头插法是在头结点后插入新节点,而尾插法则需要找到链末尾再插入。根据引用[3],单链的插入为创建和遍历,以及节点的插入修改。 然后是删除操作,需要考虑删除指定位置的节点,或者根据值删除节点。删除时要注意找到前驱节点,修改指针指向。还有链的遍历和打印,这部需要从头结点开始逐个访问,直到NULL为止。引用[4]提到链打印函数中的phead可能为空,但头结点存在的话,phead应该不为空,所以是否需要断言可能需要考虑。 链的反转也是一个重要操作,引用[2]和引用[3]都提到反转的方法,比如迭代法或递归法。反转时需要调整每个节点的next指针,指向前一个节点。另外,统计有效节点数量、查找倒数第k个节点这些面试题也是常见操作,需要遍历链并计数或使用快慢指针。 还要注意内存管理,比如销毁链时需要释放每个节点,避免内存泄漏。此外,判断链是否为空,只需要检查头结点的next是否为NULL。 可能用户还关心如何实现这些操作的代码,比如用C语言还是其他语言。根据引用[3],Java的实现也有类似的方法,但用户问题中提到的引用[1]是关于C语言的,所以可能需要用C来示例。同时,引用[5]中的结构体定义是C语言的,所以代码示例应该用C。 需要确保每个操作的步骤正确,比如插入时新节点的next指向原后继,前驱的next指向新节点。删除时要处理前驱和后继的连接。反转操作可能需要三个指针:前驱、当前、后继,逐个反转指向。 在回答时,应该点列出各个操作,并给出实现思路和代码示例。同时,按照用户要求,代码要使用正确的格式,比如用反引号包裹。注意用户提到要使用中文回答,并且生成相关问题。最后,根据引用内容添加正确的引用标识,如[^3][^5]等。 需要检查是否有遗漏的操作,比如查找节点、修改节点值等,但用户可能主要关注插入、删除、反转、遍历等基本操作。此外,带头节点的链与不带头节点的区别可能在初始化、插入头结点时的处理上,需要明确说明。</think>### 带头结点的单链常见操作汇总 带头结点的单链通过引入一个**不存储实际数据的头节点**,简化了插入、删除等操作的边界条件处理[^5]。以下是其核心操作的实现方法: --- #### 一、数据结构定义 ```c typedef int ELEM_TYPE; typedef struct Node { ELEM_TYPE mdata; // 数据域 struct Node* pnext; // 指针域 } Node, *Link; ``` --- #### 二、基础操作实现 1. **初始化链** ```c Link InitList() { Link head = (Link)malloc(sizeof(Node)); // 创建头结点 head->pnext = NULL; // 空链 return head; } ``` 2. **头插法插入节点** ```c void InsertHead(Link head, ELEM_TYPE val) { Link newnode = (Link)malloc(sizeof(Node)); newnode->mdata = val; newnode->pnext = head->pnext; // 新节点指向原首节点 head->pnext = newnode; // 头节点指向新节点 } ``` 3. **尾插法插入节点** ```c void InsertTail(Link head, ELEM_TYPE val) { Link cur = head; while (cur->pnext != NULL) { // 找到尾节点 cur = cur->pnext; } Link newnode = (Link)malloc(sizeof(Node)); newnode->mdata = val; newnode->pnext = NULL; cur->pnext = newnode; } ``` 4. **按位置删除节点** ```c void DeleteByPos(Link head, int pos) { if (pos < 1) return; Link prev = head; for (int i = 0; prev != NULL && i < pos-1; i++) { prev = prev->pnext; // 找到待删节点的前驱 } if (prev == NULL || prev->pnext == NULL) return; Link del = prev->pnext; prev->pnext = del->pnext; // 跳过待删节点 free(del); } ``` 5. **链反转(迭代法)** 通过三个指针调整节点指向[^3]: ```c void ReverseList(Link head) { if (head->pnext == NULL) return; Link prev = NULL, cur = head->pnext, next; while (cur != NULL) { next = cur->pnext; // 保存后继 cur->pnext = prev; // 反转指向 prev = cur; cur = next; } head->pnext = prev; // 头结点指向新首节点 } ``` 6. **遍历链** ```c void TraverseList(Link head) { Link cur = head->pnext; while (cur != NULL) { printf("%d ", cur->mdata); cur = cur->pnext; } } ``` --- #### 三、进阶操作 - **统计有效节点数**:遍历链计数,跳过头结点 $$ \text{长度} = \sum_{i=1}^{n} (1), \quad \text{当节点存在时} $$ - **查找倒数第k个节点**:快慢指针法,快指针先走k步[^3] - **判断链是否为空**:检查头结点的`pnext`是否为`NULL` - **销毁链**:逐个释放节点,保留头结点 --- #### 四、优势与注意事项 1. **优势**:统一操作逻辑,避免处理头节点的特殊情况 2. **注意**:插入/删除操作需正确处理指针顺序,避免内存泄漏[^4] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值