单向链表详解

#include<stdio.h>
#include<stdlib.h>
#define T 1
#define F 0

typedef int Elementtype;    //重命名int为Elementtype
typedef int Status;               //重命名int为Status,作为函数的返回类型

struct Node                            //建立链表的结构体
{
    Elementtype value;         //链表中节点的数据域可以为各种类型(在此以整形数来代替)
    struct Node *next;          //链表中节点的指针区域
};

Status init(struct Node **p);  //初始化头结点

Status print(struct Node *p);     //将链表输出

Status lenth(struct Node *p);    //计算链表的长度(在此程序中定义链表的第一个可用节点为0号位,和数组下标一样)

Status insert_head(struct Node *p, Elementtype value);  //头插,新来的节点接到头结点的后面

Status insert_tail(struct Node *p, Elementtype value);     //尾插,新来的节点接到链表NULL之前

Status insert_index(struct Node *p, int index, Elementtype value); //中间插,新来的节点放在下标index处

Status delete_index(struct Node *p, int index);                   //删除,将下标index处的节点删除(用free释放)

Status delete_value(struct Node *p, Elementtype value);//删除,将数据域为value的节点删除

Status update_index(struct Node *p, int index, Elementtype value);                               //修改数据,将下标index处改为value

Status update_value(struct Node *p, Elementtype old_value, Elementtype new_value); //修改数据,将老的数据old_value改为new_value

Status query_value(struct Node *p, Elementtype value);//查找value所处的下标

Status query_index(struct Node *p,int index); //查找下标index的数据(value)

Status empty(struct Node *p); //清空链表

Status destroy(struct Node **p);//销毁整个链表(释放头结点)

int main()
{
    struct Node *head = NULL;           //定义头结点
    init(&head);                                        //初始化头结点
    int i = 0;                                               //定义i用于循环
    
    for(i = 0; i < 20; i++)
    {
        insert_head(head, i+1);  //头插,i+1是为了从1开始插入数据;
        insert_tail(head, i+1);      //尾插
    }
    
    print(head);
    
    delete_index(head, 2);
    print(head);
    
    insert_index(head, 2, 99);
    print(head);
    
    delete_value(head, 1);
    print(head);
    
    update_index(head, 2, 88);
    print(head);
    
    update_value(head, 3, 66);
    print(head);
    
    query_value(head, 8);
    
    query_index(head,17);
    
    empty(head);
    print(head);
    
    destroy(&head);
    print(head);
    
    return 0;
}

Status init(struct Node **p)         //**p的原因是为了能改变头指针head的地址,head为struct Node *型,所以指向其地址的指针为 struct Node **型(当然,此函数可以将函数的返回值设为struct Node *型,将创建的头结点通过函数返回)                
{
    struct Node *newnode = (struct Node *)malloc(sizeof(struct Node));  //用malloc申请类型为struct Node *大小为struct Node(如果写成struct Node*就为地址的大小,不是结构体的大小)的堆空间
    if(NULL == newnode)
    {
        return F; //空间申请不成功,返回fault
    }
    
    newnode->next = NULL;  //头结点初始化
    newnode->value = 0; 
    *p = newnode;          //将newnode的地址赋给*p(head的地址此时也为newnode)
}

Status print(struct Node *p) 
{
    if(p == NULL)                //如头指针为空则说明无此链表
    {
        printf("无此链表\n");
        return F;
    }
    
    if(p->next == NULL)          //如果头指针的下一个节点为空则说明有链表但链表无数据
    {
        printf("链表为空\n");
        return F;
    }
    
    while(p->next != NULL)            //当p->next不为空
    {
        printf("%4d",p->next->value); //输出p->next的数据域
        p = p->next;                                  //移动到下一个节点处,达到循环的目的
    }
    printf("\n");
    
    return T;
}

Status insert_head(struct Node *p, Elementtype value)              //头插,(需要知道头结点的地址,以及所插入的数据内容)
{
    struct Node * new = (struct Node *)malloc(sizeof(struct Node)); //用malloc申请一个节点所需的空间
    if(NULL == new)                                                                                         //申请的空间为NULL则说明申请不成功
    {
        return F;
    }
    
    new->next = NULL;                                               //初始化新节点的指针域
    new->value = value;                                             //将所要的数据给新节点的数据域
    
    new->next = p->next;                                            //头插时先将新节点的指针域指向头结点的下一个节点
    p->next = new;                                                  //再将头结点的指针域指向新节点(这样不会出错,如果操作步骤返了会将头结点的下一个指针域覆盖,从而使链表断开)
    
    return T;
}

Status insert_tail(struct Node *p, Elementtype value)                //尾插,(需要知道头结点的地址,以及所插入的数据内容)
{
    struct Node *new = (struct Node *)malloc(sizeof(struct Node));   //用malloc申请一个节点所需的空间
    if(NULL == new)                                                  //申请的空间为NULL则说明申请不成功
    {
        return F;
    }
    
    new->next = NULL;                                                 //初始化新节点的指针域
    new->value = value;                                               //将所要的数据给新节点的数据域
    
    while(NULL != p->next)                                            //遍历找到链表的结尾
    {
        p = p->next;                                                  
    }
    
    p->next = new;                                                    //将新节点放在尾部
    
}

Status insert_index(struct Node *p, int index, Elementtype value)     //中间插,(需要知道头结点的地址,所插入的位置,以及数据内容)  
{
    int i = 0;                                                        //用于循环
    
    struct Node *new = (struct Node *)malloc(sizeof(struct Node));    //用malloc申请一个节点所需的空间
    new->next = NULL;
    new->value = value;
    
    if(index < 0 || index > lenth(p) - 1)                             //判断所设定的index在不在可操作范围内
    {
        printf("index error/n");                                      
        return F;
    }
    
    for(i = 0; i < index; i++)                                        //找到要插入的位置
    {
        p = p->next;
    }
    
    new->next = p->next;                                              //将新节点插入到index的位置上
    p->next = new;
    
    return T;
}

Status lenth(struct Node *p)                                          //判断链表的长度
{
    int len = 0;                                                                   //定义一个长度
    while(NULL != p->next)                                            //遍历,记录长度
    {
        len++;
        p = p->next;
    }
    return len;                                                       //将所得的长度返回
}

Status delete_index(struct Node *p, int index)                        //按位置删除
{
    int len = 0;                                                           
    int i = 0;
    struct Node * temp = NULL;
    
    len = lenth(p);
    if(index < 0 || index > len-1)
    {
        printf("index error\n");
        return F;
    }
    
    for(i = 0; i < index; i++)                                         //找到要删除的位置
    {
        p = p->next;
    }
    
    temp = p->next;                                                    //将删除处的前后两个节点连接
    p->next = temp->next;                                              
    free(temp);                                                            //将删除的节点释放
    temp = NULL;                                                       //将temp指向空,防止野指针

    return T;
}

Status delete_value(struct Node *p, Elementtype value)                 //按值删除
{
    int flag = 0;                                                      //定义flag判断是否找到值
    struct Node * temp = NULL;
    while(NULL != p->next)                                             //遍历找值
    {
        if(p->next->value == value)
        {
            temp = p->next;
            p->next = temp->next;
            free(temp);
            temp = NULL;
            flag = 1;                                                  //将值删除后,flag = 1
        }
        else
        {
            p = p->next;
        }
    }
    
    if(flag == 0)                                                      //如果flag等于0说明没找到值
    {
        printf("未找到value\n");
    }
    
    return T;
}

Status update_index(struct Node *p, int index, Elementtype value)      //按位置修改
{
    int i = 0;
    
    if(index < 0 || index > lenth(p)-1)
    {
        printf("index error\n");
        return F;
    }
    
    for(i = 0; i < index; i++)                                         //找到要修改的位置
    {
        p = p->next;
    }
    
    p->next->value = value;                                            //新值给旧值
    
    return T;
    
}

Status update_value(struct Node *p, Elementtype old_value, Elementtype new_value)  //按值删除
{
    while(NULL != p->next)                                                         //遍历找值
    {
        if(p->next->value == old_value)
        {
            p->next->value = new_value;                                            //修改
        }
        
        p = p->next;                                                               
    }
    return T;
}

Status query_value(struct Node *p, Elementtype value)                              //通过值查位置
{
    int data = 0;                                                                  //记录位置
    
    while(NULL != p->next)                                                         //遍历
    {
        if(p->next->value == value)
        {
            printf("%d addr is %d\n",value,data);
        }
        p = p->next;
        data++;
    }
    printf("\n");
    return T;
}

Status query_index(struct Node *p,int index)                                      //通过位置查找值
{
    int i = 0;
    
    if(index < 0 || index > lenth(p) - 1)
    {
        printf("index error\n");
        return F;
    }
    
    for(i = 0; i < index; i++)                                                    //找位置
    {
        p = p->next;
    }
    
    printf("addr%d value is %d\n",index,p->next->value);
    
    return T;
    
}

Status empty(struct Node *p)                                                      //清空
{
    struct Node * temp = NULL;
    while(p->next != NULL)                                                        //遍历删除
    {
        temp = p->next;
        p->next = temp->next;
        free(temp);
        temp = NULL;
    }
    
    return T;
}

Status destroy(struct Node **p)                                                   //销毁
{
    struct Node * temp = NULL;                                                    
    while((*p)->next != NULL)                                                     //遍历删除   
    {
        temp = (*p)->next;
        (*p)->next = temp->next;
        free(temp);
        temp = NULL;
    }
    free(*p);                                                                      //释放头结点
    *p = NULL;
    return T;
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值