作业-day-240417

实现双向链表的头插、头删、尾插、尾删、按位置插入、按位置删除

double_list.h头文件代码:

#ifndef __DOUBLE_LIST_H__
#define __DOUBLE_LIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct node
{
        int data;
        struct node *pri;   //前一个结点地址
        struct node *next;  //后一个结点地址
}node,*node_p;

//创建双向链表
node_p create_double_list();

//创建结点
node_p create_node(int data);

//链表判空
int empty_double(node_p H);

//头插
void insert_head(node_p H,int data);

//尾插
void insert_tail(node_p H,int data);

//按位插入
void insert_pos(node_p H,int data,int pos);

//头删
void del_head(node_p H);

//尾删
void del_tail(node_p H);

//按位删除
void del_pos(node_p H,int pos);

//输出
void show_double(node_p H);

#endif

double_list.c自定义函数代码:

#include "double_list.h"

//创建双向链表
node_p create_double_list()
{
        //申请空间
        node_p H=(node_p)malloc(sizeof(node));
        //判空
        if(H==NULL)
        {
                printf("空间申请失败\n");
                return NULL;
        }
        //创建头结点
        //头结点数据位,记录结点数,初始值0
        H->data=0;
        //前结点地址为NULL
        H->pri=NULL;
        //后结点地址为NULL
        H->next=NULL;
}

//创建结点
node_p create_node(int data)
{
        //申请空间
        node_p new=(node_p)malloc(sizeof(node));
        //判空
        if(new==NULL)
        {
                printf("空间申请失败\n");
                return NULL;
        }
        new->data=data;
        return new;
}
//链表判空
int empty_double(node_p H)
{
        //入参判空
        if(H==NULL)
        {
                printf("入参为空\n");
                return -1;
        }
        return H->next==NULL?1:0;
}

//头插
void insert_head(node_p H,int data)
{
        //入参判空
        if(H==NULL)
        {
                printf("入参为空\n");
                return;
        }
        //创建新结点
        node_p new=create_node(data);
        //将new->next指向头结点next指向的地址
        new->next=H->next;
        //若第一个结点存在,则要将原第一个结点的pri指向new
        if(H->next!=NULL)
                H->next->pri=new;
        //将新结点pri指向头结点地址
        new->pri=H;
        //将头结点next指向new
        H->next=new;
        //结点个数自增
        H->data++;
}

//尾插
void insert_tail(node_p H,int data)
{
        //入参判空
        if(H==NULL)
        {
                printf("入参为空\n");
                return;
        }
        //先找到尾结点
        //定义一个结点,指向头结点
        node_p p=H;
        //循环找到尾节点
        while(p->next!=NULL)
                p=p->next;//指向下个结点
        //最终p为尾节点

        //创建新结点
        node_p new=create_node(data);
        //将new->next指向原尾节点next指向的地址,NULL
        new->next=p->next;
        //将new->pri指向原尾节点地址
        new->pri=p;
        //将原尾节点next指向new的地址
        p->next=new;
        //结点个数自增
        H->data++;
        return;
}


//按位插入
void insert_pos(node_p H,int data,int pos)
{
        //入参判空
        if(H==NULL)
        {
                printf("入参为空\n");
                return;
        }
        //插入位置合理性判断
        //pos表示插入第几个位置
        if(pos<=0||pos>H->data+1)
        {
                printf("输入的位置不合理\n");
                return;
        }
        //先找到pos-1位置的结点
        //定义p,初始化为头结点地址
        node_p p=H;
        //循环找到pos-1位置地址
        for(int i=0;i<pos-1;i++)
                p=p->next;
        //此时p为pos-1位置结点地址

        //创建新结点
        node_p new=create_node(data);
        //new->next指向pos位置结点的地址
        new->next=p->next;
        //若pos位置结点地址不为NULL
        //则要将pos结点的pri指向new地址
        if(p->next!=NULL)
                p->next->pri=new;
        //新结点pri指向pos-1位置结点地址
        new->pri=p;
        //pos-1位置结点next指向新结点地址
        p->next=new;
        //结点个数自增
        H->data++;
        return;
}

//头删
void del_head(node_p H)
{
        //入参判空
        if(H==NULL)
        {
                printf("入参为空\n");
                return;
        }
        //链表判空
        if(empty_double(H))
        {
                printf("链表为空\n");
                return;
        }
        //先保存要删除的结点
        node_p del=H->next;
        //定义结点,指向第二结点地址
        node_p p=H->next->next;
        //将头结点next指向第二个结点
        H->next=p;
        //若第二个结点不为NULL,需将第二个结点pri指向头结点
        if(p!=NULL)
                p->pri=H;
        //释放掉要删除的结点空间
        free(del);
        //结点个数自减
        H->data--;
        return;
}

//尾删
void del_tail(node_p H)
{
        //入参判空
        if(H==NULL)
        {
                printf("入参为空\n");
                return;
        }
        //链表判空
        if(empty_double(H))
        {
                printf("链表为空\n");
                return;
        }

        //先找到倒数第二个结点
        node_p p=H;
        while(p->next->next!=NULL)
                p=p->next;
        //此时p为倒数第二个结点地址
        //保存要删除的结点
        node_p del=p->next;
        //将倒二结点next指向尾结点next指向的地址,NULL
        p->next=p->next->next;
        //释放掉要删除的结点空间
        free(del);
        //pri指针置空
        del->pri=NULL;
        //结点个数自减
        H->data--;
        return;
}

//按位删除
void del_pos(node_p H,int pos)
{
        //入参判空
        if(H==NULL)
        {
                printf("入参为空\n");
                return;
        }
        //链表判空
        if(empty_double(H))
        {
                printf("链表为空\n");
                return;
        }
        //删除位置合理性判断
        //pos表示删除第几个位置
        if(pos<=0||pos>H->data)
        {
                printf("输入的位置不合理\n");
                return;
        }
        //先找到pos-1位置的结点
        //定义p,初始化为头结点地址
        node_p p=H;
        //循环找到pos-1位置地址
        for(int i=0;i<pos-1;i++)
                p=p->next;
        //此时p为pos-1位置结点地址

        //保存要删除的结点地址
        node_p del=p->next;
        //定义q,指向pos+1结点地址
        node_p q=p->next->next;
        //将pos-1结点next指向pos+1结点地址
        p->next=q;
        //若pos+1结点地址不为NULL,其pri需指向pos-1地址
        if(q!=NULL)
                q->pri=p;
        //释放要删除的结点空间
        free(del);
        del->pri=NULL;
        //结点个数自减
        H->data--;
        return;
}

//输出
void show_double(node_p H)
{
        //入参判空
        if(H==NULL)
        {
                printf("入参为空\n");
                return;
        }
        //链表判空
        if(empty_double(H))
        {
                printf("链表为空\n");
                return;
        }
        //定义结点,指向第一个结点地址
        node_p p=H->next;
        while(p!=NULL)
        {
                printf("%d->",p->data);
                p=p->next;
        }
        printf("NULL\n");
}

main.c主函数代码:

int main()
{
        node_p H=create_double_list();
        printf("判空为:%d\n",empty_double(H));
        insert_head(H,10);
        insert_head(H,20);
        insert_head(H,30);
        insert_head(H,40);
        insert_head(H,50);
        insert_head(H,60);
        show_double(H);
        insert_tail(H,70);
        show_double(H);
        insert_pos(H,33,2);
        show_double(H);
        insert_pos(H,22,100);
        show_double(H);
        del_head(H);
        show_double(H);
        del_tail(H);
        show_double(H);
        del_pos(H,4);
        show_double(H);

        return 0;
}

运行结果:

链表和顺序表的区别

1、逻辑结构相同:都是线性结构。

        物理结构不同:顺序表是顺序结构,物理地址连续;链表是链式结构,物理地址不连续。

2、顺序表通过下标访问元素,链表通过指针访问元素

3、顺序表查询速度快,插入、删除速度慢;

        链表查询速度慢,插入、删除速度快。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值