指针的指针---一个有序链表的实现

本文详细介绍了如何使用C语言实现链表的插入和打印功能,包括如何通过指针操作来改变链表的首地址以及如何高效地进行链表内容的增删查改。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

#define BOOL int
#define FALSE 0
#define TRUE 1

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


BOOL insert(Node **root,int new_value);
void print(Node *root);

int main (int argc, const char * argv[])
{
    Node *root;
    insert(&root, 22);
    insert(&root, 23);
    insert(&root, 12);
    insert(&root, 26);
    
    print(root);
    
    int a = 10;
    int *p = &a;
    printf("%d,%d",p,*p);
    return 0;
}

BOOL insert(Node **root,int new_value){
    
    Node *current;
    Node *previous;
    Node *new;
    
    //root指的就是链表首节点的指针的地址,
    //现在current指向root指向的内容,就是链表指针,也就是链表首节点的地址,
    //如果改变current的值只能影响到链表中的内容,不能影响到链表首地址的地址。
    //如果想改变链表首地址的地址,只能用*root。
    current = *root;
    previous = NULL;
    
    while (current != NULL && current->value < new_value) {
        previous = current;
        current = current->next;
    }
    
    new = (Node *)malloc(sizeof(Node));
    if (new == NULL) {
        return FALSE;
    }
    new->value =new_value;
    new->next = current;
    
    if (previous == NULL) {
        *root = new;
    }
    else
        previous->next = new;
    
    return TRUE;
    
}

void print(Node *root){
    while (root != NULL) {
        printf("%d\n",root->value);
        root = root->next;
    }
}

实现了添加和打印出链表内容的insert和print函数。

因为链表是有序的,所以如果插入的元素是最小的,那么就要改变链表首元素的地址。如果insert参数是Node*类型的,那么只能改变

链表的内容,而不能改变链表首元素地址。

### 如何两个有序链表的交集 对于两个已排序的链表,可以通过双指针的方法高效地找到它们的交集。以下是具体的实现方法: #### 方法概述 通过维护两个指针 `p` 和 `q` 分别指向两个链表的第一个节点,逐一比较两者的值。如果两者相等,则表示该值属于交集;如果不相等,则移动较小值对应的指针向前一步。 此过程的时间复杂度为 O(m+n),其中 m 和 n 是两个链表的长度[^1]。这是因为每个节点最多被访问一次。 #### 实现细节 以下是一个完整的 C++ 实现代码示例: ```cpp #include <iostream> using namespace std; // 定义链表节点结构体 struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {} }; ListNode* findIntersection(ListNode* head1, ListNode* head2) { ListNode dummy(0); // 创建虚拟头节点 ListNode* tail = &dummy; // 尾部指针 ListNode* p = head1; // 链表1的当前节点 ListNode* q = head2; // 链表2的当前节点 while (p && q) { // 当两个链表均未到达末尾时继续 if (p->val == q->val) { // 如果值相同 tail->next = new ListNode(p->val); // 添加到结果链表 tail = tail->next; // 移动结果链表的尾部指针 p = p->next; // 同时前进两个链表指针 q = q->next; } else if (p->val < q->val) { // 值较小时前移对应链表指针 p = p->next; } else { q = q->next; } } return dummy.next; // 返回结果链表的真实头部 } void printList(ListNode* head) { ListNode* cur = head; while (cur != nullptr) { cout << cur->val; if (cur->next != nullptr) cout << " "; cur = cur->next; } cout << endl; } int main() { // 输入第一个链表 ListNode* head1 = new ListNode(0); ListNode* temp1 = head1; int num; cout << "Enter first sorted list (-1 to end):"; while (cin >> num && num != -1) { temp1->next = new ListNode(num); temp1 = temp1->next; } // 输入第二个链表 ListNode* head2 = new ListNode(0); ListNode* temp2 = head2; cout << "Enter second sorted list (-1 to end):"; while (cin >> num && num != -1) { temp2->next = new ListNode(num); temp2 = temp2->next; } // 计算交集 ListNode* result = findIntersection(head1->next, head2->next); // 输出结果 if (!result) { cout << "NULL" << endl; } else { printList(result); } return 0; } ``` #### 关键点解析 - **初始化虚拟头节点**:为了简化边界条件处理,引入了一个虚拟头节点 `dummy`,其作用是作为结果链表的起始位置。 - **双指针技术**:利用两个指针分别遍历两条链表,当遇到相同的值时将其加入结果链表,并同步推进两个指针;否则仅推进指向较小值的那个指针- **内存管理**:在实际应用中需要注意动态分配的对象释放问题,这里省略了这部分逻辑以便专注于核心算法[^2]。 #### 测试案例分析 假设输入如下: - 第一条链表:1 -> 3 -> 5 -> 7 - 第二条链表:3 -> 5 -> 8 程序会输出: ``` 3 5 ``` 这表明只有数值 3 和 5 出现在两条链表中,因此构成了最终的结果集合。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值