C 单链表

C 单链表(Singly Linked List)

/*
 * singly_linked_list.c
 * 单向链表
 * sll = singly_linked_list
 * */

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

/*
 * 节点结构 head -> |value|next| -> ...
 * */
typedef struct sll {
    int value;
    struct sll *next;
} sll;

void init_sll(sll **head);
void add_sll_node(sll **head, int value);
void add_sll_nodes(sll **head, int values[], int len);
bool del_sll_node(sll **head, int index);
sll *get_sll_node(sll *head, int index);
sll *locate_sll_node(sll *head, int value);
bool insert_sll_node(sll **head, int index, int value);
void traverse_sll(sll *head);
int length_sll(sll *head);

int main(int argc, char *argv[])
{
    sll *head;
    init_sll(&head);
    add_sll_node(&head, 1);
    int values[] =  {1, 2, 3, 5, 8, 13};
    add_sll_nodes(&head, values, 6);
    traverse_sll(head);
    del_sll_node(&head, 0);
    del_sll_node(&head, 3);
    traverse_sll(head);
    
    printf("The %d node is %p\n", 4, get_sll_node(head, 4));
    printf("The node with value %d is %p\n", 13, locate_sll_node(head, 13));
    printf("Length of List: %d\n", length_sll(head));


    insert_sll_node(&head, 0, 0);
    insert_sll_node(&head, length_sll(head), 21);
    traverse_sll(head);
    del_sll_node(&head, 4);
    traverse_sll(head);

    return 0;
}

/*
 * 初始化链表
 * 要求传入一个链表指针的地址,以便在函数中对这个指针做出更改
 * */
void init_sll(sll **head)
{
    *head = NULL;
}

/*
 * 添加节点
 * */
void add_sll_node(sll **head, int value)
{
    /* 新建一个节点 */
    sll *node = (sll *)malloc(sizeof(sll));
    node->value = value;
    node->next = NULL;

    sll *last = *head;
    if (!last) {
        /* 如果head节点是空的,说明链表为空 */
        *head = node;
    } else {
        /* 找到链表尾部,将last节点的next指向sll节点 */
        while (last->next) {
            last = last->next;
        }
        last->next = node;
    }
}

/*
 * 增加多个节点
 * */
void add_sll_nodes(sll **head, int values[], int len)
{
    for (int i = 0; i < len; i++) {
        add_sll_node(head, values[i]);    
    }
}

/*
 * 根据索引删除节点
 * 删除成功返回true,否则返回false
 * */
bool del_sll_node(sll **head, int index)
{
    /* 如果删除索引大于等于列表长度 */
    if (index >= length_sll(*head))
        return false;
    /* 删除首节点 */
    if(index==0) {
        sll *first = *head;
        sll *second = first->next;
        free(first);
        first = NULL;
        *head = second;
        return true;
    } else {
        /* 遍历到index的前一位后执行删除操作 */
        int count = 0;
        for (sll *p=*head; p; p=p->next) {
            count++;
            if (count == index) {
                sll *n = p->next;
                p->next = n->next;
                free(n);
                n = NULL;
                return true;
            }
        }
    }

    return false;
}

/*
 * 根据索引查找节点
 * 从0开始算起
 * */
sll *get_sll_node(sll *head, int index)
{
    /* 重复往下寻找index次,找到第index个节点,返回节点地址,否则NULL */
    sll *node = head;
    int j = 0;
    while (node->next != NULL && j < index)
    {
        node = node->next;
        j++;
    }
    if (j == index)
        return node;
    else
        return NULL;
}

/*
 * 后插法:找到index-1位置,将节点插入到index中去
 * 在index位置插入value
 * */
bool insert_sll_node(sll **head, int index, int value)
{
    /*
     * 如果index为0,需要改变head指向
     * */
    if (index == 0) {
        sll *node = (sll *)malloc(sizeof(sll));
        node->value = value;
        node->next = *head;
        *head = node;
        return true;
    }
    /*
     * 找到index-1位置的节点,如果节点不存在,不能插入
     * */
    sll *p, *s;
    p = get_sll_node(*head, index-1);
    if (p == NULL) {
        printf("wrong index\n");
        return false;
    } else {
        /*
         * 新建节点s
         * s->next指向原先p->next
         * p->next指向s
         * */
        s = (sll *)malloc(sizeof(sll));
        s->value = value;
        s->next = p->next;
        p->next = s;
        return true;
    }
}

/*
 * 根据值查找节点 
 * */
sll *locate_sll_node(sll *head, int value)
{
    for (sll *p=head; p; p=p->next) {
        if (p->value == value)
            return p;
    }
    return NULL;
}

/*
 * 遍历打印链表
 * */
void traverse_sll(sll *head)
{
    for (sll *p=head; p; p=p->next) {
        printf("%d -> ", p->value);
    }
    printf("NULL\n");
}

/*
 * 链表长度
 * */
int length_sll(sll *head)
{
    int len = 0;
    
    for (sll *p=head; p; p=p->next) {
        len++;
    }

    return len;
}
posted @ 2019-12-20 22:41  no樂on  阅读(398)  评论(0编辑  收藏  举报