单链表总结篇

【基本概念】单链表即单向链表,数据结构为一个接一个的结点组成,每个结点有两个成员,一个数据域一个指向下一个结点的指针,如下:

struct Node
{
    int data;
    struct Node *next;
};

单链表基本操作包括链表初始化、插入、删除,其中初始化操作是指让单链表存在一个头结点,其数据域随机,头结点指向下一个结点,每次访问都要从头结点开始访问,插入结点方式有两种,尾部插入和结点前部插入,尾部插入很简单与正常的输入顺序一致,而前部插入需要时常变动头结点的指针,始终让他指向新插入的,因为如果不调整头指针的话,在输出时是无法从头结点往前访问的,记住,它是单向链表。删除操作主要是定值查找删除,在链表里并不需要做什么删除操作,其实就是将前一结点指针指向目标节点的下一个结点位置,指针访问时直接跳跃,即可实现删除操作。


【测试代码】

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

typedef int data_type;

typedef struct Node node_t;// 给struct Node取个别名node_t
typedef struct Node * node_ptr;//给struct Node*取个别名node_ptr

typedef struct Node
{
    data_type data;
    struct Node *node_next;//node_next是一个指向结构的指针,告诉指针要指向的地址就要付给它一个结构类型地址
};

//链表初始化
node_t * init()
{
    node_ptr p;
    p = (node_t *)malloc(sizeof(node_t));
    p->node_next = NULL;
    return p;
}
//在链表后面插入结点
node_t *insert_back(node_ptr p , data_type data)
{


    node_ptr pnew = (node_t *)malloc(sizeof(node_t));
    pnew ->node_next = NULL;
    pnew ->data = data;

    p->node_next = pnew;

    return pnew;
}

void remove(node_ptr p, data_type data)
{
    node_ptr find = p;
    if(!find)
        return ;
    while(find->node_next->data !=data)
    {
        find= find->node_next;
    }
    find->node_next = find->node_next->node_next ;

}
//正常打印
void print(node_ptr p)
{
    if(!p)
    {
            printf("no data, you think too much");
            return ;
    }

    while(p->node_next != NULL)
    {
        printf("%d ", p->data);
        p = p->node_next;
    }
    printf("%d ", p->data);
    printf("\n");

}



void main()
{
    node_ptr pnode, list;
    pnode = init();
    list = pnode;

    pnode = insert_back(pnode, 1);
    pnode = insert_back(pnode, 2);
    pnode = insert_back(pnode, 3);
    pnode = insert_back(pnode, 4);
    pnode = insert_back(pnode, 5);
    pnode = insert_back(pnode, 6);

    printf("normal print:");
    print(list->node_next);
    printf("-------------------------------------------\n");
    remove(list,1);
    printf("remove one node 1 print:");
    print(list->node_next);
    printf("-------------------------------------------\n");
    remove(list,2);
    remove(list,3);
    remove(list,4);
    remove(list,5);
    remove(list,6);
    printf("remove all print:");
    print(list->node_next);
    printf("\n-------------------------------------------\n");

}

【输出】
这里写图片描述
这段测试代码中使用的是尾部插入,设置了一个指针pnode指向尾结点,指针list始终指向头结点,访问链表时从list开始,而pnode就用于插入新结点和删除结点,插入的新节点永远在尾部后面,这样要比**list形式理解起来简单一点,大部分的资料都喜欢用双重指针,但是双重指针繁杂不易理解,尤其在访问地址变换的时候,很容易出错,所以先以这种简单的方式来理解单链表的基本思想。
结点存储方式如下
这里写图片描述
以前部插入为例,设计测试代码如下:

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

typedef int data_type;

typedef struct Node node_t;// 给struct Node取个别名node_t
typedef struct Node * node_ptr;//给struct Node*取个别名node_ptr

typedef struct Node
{
    data_type data;
    struct Node *node_next;//node_next是一个指向结构的指针,告诉指针要指向的地址就要付给它一个结构类型地址
};



node_t * init()
{
    node_ptr p;
    p = (node_t *)malloc(sizeof(node_t));
    p->node_next = NULL;
    return p;
}
//链表从前面插入
node_t * insert_front(node_ptr p , data_type data)
{
    p->data = data;
    node_ptr pnew = (node_t *)malloc(sizeof(node_t));
    pnew->node_next = p;

    return pnew;
}
void remove(node_ptr p, data_type data)
{
    node_ptr find = p;
    if(!find)
        return ;
    while(find->node_next->data !=data)
    {
        find= find->node_next;
    }
    find->node_next = find->node_next->node_next ;

}
//正常打印
void print(node_ptr p)
{
    if(!p)
    {
            printf("no data, you think too much");
            return ;
    }

    while(p->node_next != NULL)
    {
        printf("%d ", p->data);
        p = p->node_next;
    }
    printf("%d ", p->data);
    printf("\n");

}



void main()
{
    node_ptr pnode, list;
    pnode = init();


    pnode = insert_front(pnode, 1);
    pnode = insert_front(pnode, 2);
    pnode = insert_front(pnode, 3);
    pnode = insert_front(pnode, 4);
    pnode = insert_front(pnode, 5);
    pnode = insert_front(pnode, 6);
    list = pnode;

    printf("normal print:");
    print(list);
    printf("-------------------------------------------\n");
    remove(list,1);
    printf("remove one node 1 print:");
    print(list->node_next);
    printf("-------------------------------------------\n");
    remove(list,2);
    remove(list,3);
    remove(list,4);
    remove(list,5);
    remove(list,6);
    printf("remove all print:");
    print(list->node_next);
    printf("\n-------------------------------------------\n");

}

【输出】
这里写图片描述
注意两个测试代码输出有什么区别,前向插入,是倒着输出的,跟输入顺序不一样。
其他单链表相关操作都是在此基础上做的,忘记了单链表怎么操作时可以参考的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值