有序单链表的建立

本文介绍了如何使用C语言创建并操作有序单链表。内容来源于《C和指针》一书,详细阐述了链表的基本操作和有序插入的方法。

从C和指针这本书上搬来的:

/*
**插入到一个有序地单链表,函数的参数是一个指
**向链表第一个节点的指针以及需要插入的值。
*/

#include <stdio.h>
#include <stdlib.h>

#define TRUE    1
#define FALSE   0

typedef struct NODE{
    struct NODE *next;
    int value;
}Node;


int insert1(Node **first,int new_value)
{
    Node *current = *first;
    Node *pre = NULL;
    
    Node *newNode;
    newNode = (Node *)malloc(sizeof(Node));
    if(newNode == NULL)
        return FALSE;
    newNode->value = new_value;
    
    while(current != NULL && current->value < new_value)    //temp不为空,应在判断前!
    {
        pre = current;
        current = current->next;
    }                                                                                    
       
    newNode->next = current;
    if(pre == NULL)             //新节点位于链表首部,包括空链表的情况
        *first = newNode;        
    else                               
        pre->next = newNode;  
 
    return TRUE;
}


/*
**消除链表
<think>嗯,用户想了解如何建立一个有序递增的单链表。那我得先回忆一下单链表的基本结构,然后考虑怎么在插入时保持有序。首先,单链表每个节点应该包含数据域和指向下一个节点的指针。然后,插入的时候需要找到合适的位置,使得插入后的链表依然有序。 可能得分为两种情况:空链表时直接插入,非空链表时找到第一个比插入值大的节点,然后插入到它的前面。但怎么处理头节点的情况呢?可能需要一个指针从头开始遍历,直到找到合适的位置。或者,使用两个指针,一个记录当前节点,一个记录前驱节点,这样插入的时候可以修改前驱节点的next指向新节点,新节点的next指向当前节点。 还有,要考虑插入的数比所有节点都大,这时候要插到末尾。或者比头节点还小,这时候要更新头节点。可能需要逐个比较节点的值,找到正确的位置。比如,初始化链表为空,每次插入新节点时,从头节点开始比较,直到找到第一个大于新节点值的节点,然后插入到该节点之前。 另外,是否可以考虑用递归的方法?不过对于单链表,可能迭代的方式更直观,容易理解和实现。比如,使用一个循环来遍历链表,同时保持前驱节点和当前节点的指针,当找到合适的位置时,插入新节点。 还有,要注意边界情况,比如链表为空、插入到头部、中间或尾部。每种情况都要处理正确,否则会导致链表断裂或者顺序错误。比如,当链表为空时,新节点就是头节点;当插入位置在头节点之前,新节点成为新的头节点;否则正常插入中间或末尾。 然后,具体的步骤可能需要这样:首先创建新节点,然后判断链表是否为空,如果空则直接插入。否则,从头节点开始遍历,比较当前节点的值与新节点的值,如果当前节点的值小于新节点的值,则继续向后遍历,直到找到第一个大于或等于的节点,或者到达末尾。然后,将新节点插入到该位置的前面,可能需要调整前驱节点的next和新节点的next指针。 举个例子,假设现有链表是1->3->4,要插入2。遍历时,1小于2,继续;3大于2,所以插入到1和3之间,形成1->2->3->4。这时候需要把1的next指向2,2的next指向3。 可能还需要考虑重复值的情况,比如是否允许重复?题目说是递增有序,所以可能允许,所以插入的位置是第一个大于等于的位置的前面。 在代码实现上,可能需要一个函数,接收头节点的引用和新值,然后处理插入。需要注意头节点可能被改变,所以可能需要返回新的头节点,或者使用指向指针的指针来处理。 总的来说,建立有序递增单链表的关键在于每次插入时找到正确的位置,并调整指针。需要考虑各种边界情况,确保插入后的链表保持有序。</think>建立有序递增单链表的关键在于每次插入新节点时,确保其数值在链表中按升序排列。以下是详细步骤和原理分析: --- ### **一、单链表结构定义** 每个节点包含两部分: ```c typedef struct Node { int data; // 数据域 struct Node *next; // 指针域,指向下一个节点 } Node; ``` --- ### **二、有序插入的核心逻辑** #### **1. 边界情况处理** - **空链表**:直接插入新节点作为头节点。 - **新节点值 < 头节点值**:将新节点插入链表头部。 #### **2. 一般情况处理** 从头节点开始遍历,找到**第一个大于等于新节点值**的位置,插入到该位置之前: - 使用双指针 `prev`(前驱节点)和 `curr`(当前节点)。 - 终止条件:`curr == NULL`(插到末尾)或 `curr->data >= new_data`(插到中间)。 --- ### **三、具体实现步骤** ```c Node* insertSorted(Node *head, int new_data) { // 创建新节点 Node *new_node = (Node*)malloc(sizeof(Node)); new_node->data = new_data; new_node->next = NULL; // 情况1:链表为空 或 新节点值 < 头节点值 if (head == NULL || new_data < head->data) { new_node->next = head; head = new_node; // 更新头节点 return head; } // 情况2:寻找插入位置 Node *prev = head; Node *curr = head->next; while (curr != NULL && curr->data < new_data) { prev = curr; curr = curr->next; } // 插入新节点到prev和curr之间 prev->next = new_node; new_node->next = curr; return head; } ``` --- ### **四、实例演示** #### **初始链表**:$$1 \rightarrow 3 \rightarrow 4$$ #### **插入值**:`2` 1. 遍历链表,发现 `1 < 2 < 3`。 2. 在 `1` 和 `3` 之间插入 `2`。 3. **结果链表**:$$1 \rightarrow 2 \rightarrow 3 \rightarrow 4$$ --- ### **五、时间复杂度分析** - **最优情况**:插入到头部,时间复杂度为 $$O(1)$$ - **最差情况**:插入到末尾,需遍历整个链表,时间复杂度为 $$O(n)$$ --- ### **六、关键注意事项** 1. **内存管理**:插入新节点时需动态分配内存(`malloc`),避免内存泄漏。 2. **指针修改顺序**:先设置 `new_node->next = curr`,再更新 `prev->next`,防止链表断裂。 3. **头节点更新**:当插入到链表头部时,必须返回新的头节点。 通过以上方法,可以确保单链表始终保持有序递增。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值