数据结构—链表初步

链表结构介绍及形状

在这里插入图片描述

链表添加及代码表示

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

typedef struct _node {//用typedef是为了后面不再需要打struct,节省时间
    int value;
    struct _node *next;//用struct是因为编译器还未到node,无法用node定义
} node;

int main()
{
    int number;
    node *head = NULL;
    do{//先读入number,若用while,则不能先输入number
        scanf("%d",&number);
        if(number != -1)
        {
        	//add to linked-list(将新元素加入链表)
            node *p = (node*) malloc (sizeof(node));//申请一个_node大小的空间存放
            p->value = number;
            p->next = NULL;
            //find the last(找到链表的最后一个结点)
            node *last = head;//定义一个last的指针,指代最后一个结点的位置。在一开始链表没有元素时,直接跳到else
            if( last )//当last不等于NULL,可以往下走
            {
                while( last->next )//当last->next不等于NULL时,令last指向结点内的指针元素,即指向下一个结点的首地址
                {
                    last = last->next;
                }
                //attach(添加)
                last->next = p;//链表最后一个结点的next由NULL指向了新添加的结点的首地址
            }
            else
            {
                head = p;//当last等于NULL时,head=p,使p成为了链表的第一个结点
            }
        }
    }while(number != -1);
    
    return 0;
}

链表函数

将main函数内,添加链表元素的代码独立成一个函数.

下面为错误代码,因为下面传递的是指向指针 head 的指针,而在 add 函数中修改了指针 head 的值,从而改变了 main 函数中的 head 指针指向的位置,这会影响链表结构的修改。因此需要传递指针的指针

因为head未指向任何东西,所以传进去add函数的为指针的地址,而

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

typedef struct _node {
    int value;
    struct _node *next;
} node;

typedef struct _list{//
    node *head;
}List;

void add(List *plist, int number)
{
    //add to linked-list(将新元素加入链表)
            node *p = (node*) malloc (sizeof(node));
            p->value = number;
            p->next = NULL;
    //find the last(找到链表的最后一个结点)
            node *last = plist->head;//从第一个开始找到最后结点
            {
                while( last->next )//当last->next不等于NULL时,令last指向结点内的指针元素,即指向下一个结点的首地址
                {
                    last = last->next;
                }
     //attach(添加)
                last->next = p;//链表最后一个结点的next由NULL指向了新添加的结点的首地址
            }
            else
            {
                plist->head = p;//当last等于NULL时,plist->head=p,使之记住第一个结点地址
            }
}

int main()
{
    int number;
    List list;
    list->head = NULL;
    
    do{
        scanf("%d",&number);
        if(number != 0)
        {
            add(&list, number);
        }
    }while(number != 0);
    
    return 0;
}

链表搜索

此循环可以遍历整个链表,输出每一个值,插在主函数"return 0"之前

node *p;
for(p = list.head; p; p = p->next)//遍历首地址为链表首地址;只要p还存在(即不到最后一个结点,不为NULL),遍历继续;每一次操作结束后指向下一个结点首地址
{
    printf("%d\t", p->value);
}

当要搜索一个链表内的数字,便可使用遍历去匹配这个数字,再进行其他操作

链表的删除

利用链表的搜索,找到要操作的数字,再继续删除

如何删除呢?

  • 将删除结点前的next指向后一个结点的首地址

  • 定义两个指针,初始化一个为NULL,利用一个指针p指向要删除的结点的首地址;当搜索到的结点为目标结点,则让q的next等于p的next,即指向目标结点的下一个,再free掉目标结点

node *p, *q;
scanf("%d", &number);
for(q = NULL,p = list.head; p; p = p->next)//相应设置
{
    if(p->value == number)//如果为目标结点,则进入循环,否则p指向下一个,for循环的结束操作
    {
        if( q )//要先保证q不为NULL,即第一个结点刚刚好是目标结点时,令它单独操作,因为->左边有NULL,编译器会识别为error
        {
            q->next = p->next;//令目标节点的next指向目标节点下一个首地址
        }
        else
        {
            list.head = p->next;//当第一个结点刚刚好是目标结点时,转移链表首地址,以方便下面free操作
        }
        free(p);
        break;
    }
}

链表的清除

node *p, *q;
for(p = list.head; p; p = q)//从第一个节点开始;p不为NULL,即不为最后一个节点;操作结束后让p变成下一个节点首地址继续操作
{
	q = p->next;//保留下一个节点首地址
    free(p);//找一个free一个
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值