自己写的第一个链表程序

# include <stdio.h>
# include <malloc.h>
 
struct Node
{
    int data;
    struct Node * next;
};
 
struct Node * create_list()
{
    int len;
 
    printf("请输入节点个数:");
    scanf("%d", &len);
 
    struct Node * pHead = (struct Node *)malloc(sizeof(struct Node));
    struct Node * p = pHead;
 
    pHead->data = NULL;
 
    for (int i = 0; i < len; i++)
    {
        struct Node * pNew = (struct Node *)malloc(sizeof(struct Node));
 
        pHead->next = pNew;
        pNew->data = i;
        pNew->next = NULL;
        pHead = pNew;
 
    }
 
    return p;
}
 
void traverse_list(struct Node * pHead)
{
    while (pHead)
    {
        printf("%d\n", pHead->next->data);
        pHead = pHead->next;
    }
 
    return;
}
 
int main(void)
{
    traverse_list(create_list());
 
    return 0;
}

### 带哨兵节点的单向链表实现 带哨兵节点(也称为头节点或哑结点)的单向链表是一种常见的数据结构设计方式,能够简化边界条件处理并增强代码可读性和健壮性。下面展示了一个完整的C语言实现方案。 #### 初始化链表 为了创建一个带有哨兵节点的单向链表,首先定义链表节点的数据结构,并初始化链表: ```c #include <stdio.h> #include <stdlib.h> // 定义链表节点结构体 typedef struct ListNode { int data; struct ListNode *next; } ListNode; // 创建新节点函数 ListNode* create_node(int value) { ListNode *newNode = (ListNode *)malloc(sizeof(ListNode)); newNode->data = value; newNode->next = NULL; return newNode; } // 初始化链表 ListNode* init_list() { ListNode *head = create_node(-1); // 使用-1作为哨兵位标记, 或者其他不会影响业务逻辑的特殊值 head->next = NULL; return head; } ``` 此部分通过`init_list()`函数返回指向哨兵节点的指针[^3]。 #### 插入操作 对于尾插法来说,在每次插入新的元素之前都需要遍历至链表末端再执行插入动作;而对于头插法则只需修改前驱节点即可完成新增工作。这里给出两种方法的具体实现: ##### 尾插法 ```c void append_to_tail(ListNode **ppHead, int val){ if (*ppHead == NULL || ((*ppHead)->next && (*ppHead)->next == *ppHead)){ *ppHead = init_list(); } ListNode *pNew = create_node(val); ListNode *tail = get_last(*ppHead); tail->next = pNew; pNew->next = *ppHead; // 形成环形链表特性 } ``` ##### 头插法 ```c void prepend_to_head(ListNode **ppHead, int val){ if (!*ppHead){ *ppHead = init_list(); } ListNode *pNew = create_node(val); pNew->next = (*ppHead)->next; (*ppHead)->next = pNew; } ``` 上述代码片段展示了如何利用哨兵节点来进行安全可靠的节点添加过程。 #### 遍历与显示 最后提供一个简单的遍历打印功能用于验证链表状态: ```c void traverse_and_print(const ListNode *head){ const ListNode *current = head->next; while(current != head){ printf("%d -> ", current->data); current = current->next; } puts("HEAD"); } ``` 这段程序会从真正的第一个有效节点开始访问直到重新遇到哨兵位置为止[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值