0
点赞
收藏
分享

微信扫一扫

使用springboot和vue3以及EasyExcel做导出数据(复用)

静鸡鸡的JC 03-23 17:00 阅读 2
链表

1无头单向链表

2有头单向链表

2.1链表结点结构体定义

typedef struct link_node
{
    int data;//数据域
    struct link_node *pnext;//指向下一个结点的指针
}NODE;

2.2链表头结点结构体定义

typedef struct link_lable{
    NODE *pnext;//指向首节点的指针
    int clen;//记录链表节点数量
}LABLE;

2.3单向链表头结点创建

/*=============单向链表标签(头)创建-空链表=========*/
void *create_lable(void)
{
    LABLE *pnew=NULL;

    pnew=malloc(sizeof(LABLE));//创建一个标签
    if (NULL == pnew)
	{
		perror("fail malloc");
		return NULL;
	}

    /*初始化标签成员*/
    pnew->pnext= NULL;//
    pnew->clen=0;

    return pnew;
}

2.4单向链表结点创建

/*=============单向链表结点创建==============*/
NODE * create_node(int data)
{
    NODE *pnew=NULL;

    pnew=malloc(sizeof(NODE));
    if (NULL == pnew)
	{
		perror("fail malloc");
		return NULL;
	}
	
    pnew->pnext=NULL;
    pnew->data = data;

    return pnew;
}

2.5链表非空判断

int is_empty_link(LABLE *list)
{
	return NULL == list->pnext;
}

2.6单向链表结点插入

2.6.1头插法

/*=============单向链表头插法=================*/
int push_head(LABLE *list, NODE *pnode)
{
    pnode->pnext = list->pnext;

    list->pnext=pnode;
    list->clen++;

    return 0;
}

2.6.2尾插法

/*=============单向链表尾插法=================*/
int push_tail(LABLE *list,NODE *pnode)
{
    NODE *ptmp=NULL;

    if(is_empty_link(list))
    {
        list->pnext=pnode;
    }
    else
    {
        ptmp=list->pnext;//将结点类型的中间指针变量初始化为指向首结点
        while(1)
        {
            if(NULL==ptmp->pnext)
            {
                break;
            }
            ptmp=ptmp->pnext;//不断指向下一个结点
        }
        pnode->pnext=ptmp->pnext;//新结点的指针域继承旧结点的指针域(NULL)
        ptmp->pnext=pnode;//原链表的最后一个结点的指针域指针指向新插入的结点
    }
    list->clen++;

    return 0;
}

2.7单向链表遍历

/*=============单向链表遍历===============*/
int list_for_each(LABLE *list)
{
    NODE *ptmp=NULL;

    ptmp=list->pnext;//将结点类型的中间指针变量初始化为指向首结点
    while(1)
    {
        if(NULL==ptmp)//遍历到的当前结点为空(链表最后一个结点的后面的那个还没有被创建出来的结点)
        {
            break;
        }
        printf("%d\t",ptmp->data);
        ptmp=ptmp->pnext;//不断指向下一个结点
    }
    printf("\n");

    return 0;
}

注意:

该遍历操作,最终【ptmp】并不是指向链表最后一个结点,而是【NULL】,指尾节点后面那个还未被创建出来的结点。

2.7单向链表结点删除

2.7.1头删法

/*=============单向链表头删法=================*/
int pop_head(LABLE *list)
{
    NODE *ptmp=NULL;

    if(is_empty_link(list))
    {
        return 0;
    }

    ptmp=list->pnext;//初始化结点类型的中间指针变量为链表头指针域(即代表首结点,而非头结点)
    list->pnext=ptmp->pnext;
    free(ptmp);

    list->clen--;

    return 0;
}

2.7.2尾删法

/*=============单向链表尾删法=================*/
int pop_tail(LABLE *list)
{
    NODE *ptmp=NULL;

    if(is_empty_link(list))
    {
        return 0;
    }
    else if(1==list->clen)
    {
        free(list->pnext);
        list->pnext=NULL;
    }
    else
    {
        ptmp=list->pnext;//将结点类型的中间指针变量初始化为指向首结点
        while(1)
        {
            if(NULL==ptmp->pnext->pnext)
            {
                break;
            }
            ptmp=ptmp->pnext;//不断指向下一个结点
        }
        free(ptmp->pnext);//释放最后1个结点
        ptmp->pnext=NULL;//将倒数第2个结点的指针域置空(因为它将成为新的尾结点),此时链表最后一个结点已被放逐
    }
    list->clen--;

    return 0;
}

2.8单向链表查找

/*=============单向链表查找=================*/
NODE *search_link(LABLE *list,int data)
{
    NODE *ptmp=NULL;

    ptmp=list->pnext;//初始化结点类型的中间指针变量为链表头指针域(指向首结点)
    while(1)
    {
        if(NULL==ptmp)
        {
            break;
        }

        if(data==ptmp->data)
        {
            return ptmp;
        }
        ptmp=ptmp->pnext;
    }

    return NULL;
}

2.9单向链表修改

int change_link_list(LABLE *list,int source_data,int target_data)
{
    NODE *search=NULL;

    search=search_link(list,source_data);
    if(search!=NULL)
    {
        search->data=target_data;
        return 0;
    }

    return -1;
}

2.10单向链表销毁

/*=============单向链表销毁=================*/
int destroy_link_list(LABLE *list)
{
    while(1)
    {
        if(is_empty_link(list))
        {
            break;
        }
        else
        {
            pop_head(list);
        }
    }
    free(list);

    return 0;
}

2.11单向链表的其它操作

2.11.1单向链表逆序

/*============单向链表逆序=============*/
int reverse_link_list(LABLE *list)
{
    NODE *ptmp=NULL;
    NODE *pinsert=NULL;
    
    if(is_empty_link(list))
    {
        return 0;
    }

    ptmp=list->pnext;//初始化结点类型的中间指针变量为链表头指针域(首结点)
    list->pnext=NULL;//首结点的指针域赋值NULL
    while(1)
    {
        if(NULL==ptmp)
        {
            break;
        }

        pinsert=ptmp;//待插入的结点
        ptmp=ptmp->pnext;//不断指向下一个结点

        pinsert->pnext=list->pnext;
        list->pnext=pinsert;
    }

    return 0;
}

2.11.2单向链表查找中间结点

/*============在单向链表中寻找中间结点=============*/
NODE* search_midnode_link_list(LABLE *list)
{
    NODE *fast=NULL;
    NODE *slow=NULL;

    /*初始化快慢指针为头结点的指针域(指向首结点)*/
    slow=list->pnext;
    fast=slow;
    while(1)
    {
        if(NULL==fast)
        {
            break;
        }

        fast=fast->pnext;
        if(NULL==fast)
        {
            break;
        }
        fast=fast->pnext;
        slow=slow->pnext;
    }
    return slow;
}

2.11.3单向链表查找倒数第k个结点

/*============在单向链表中寻找倒数第K个结点=============*/
NODE *search_last_k_link_list(LABLE *list,int k)
{
    NODE *p_fast=NULL;
    NODE *p_slow=NULL;

    p_fast=list->pnext;
    p_slow=p_fast;
    for(int i=0;i<k;i++)
    {
        if(NULL==p_fast)
        {
            return NULL;
        }
        p_fast=p_fast->pnext;
    }
    while(1)
    {
        if(NULL==p_fast)
        {
            break;
        }
        p_fast=p_fast->pnext;
        p_slow=p_slow->pnext;
    }

    return p_slow;
}

2.11.4单向链表删除指定结点

2.11.4.1单结点删除
/*==============删除单向链表中指定结点===============*/
int pop_appointed_node(LABLE *list,int key)
{
    NODE *p_free=NULL;
    NODE *p_pre=NULL;

    /*初始化遍历指针*/
    p_free=list->pnext;
    p_pre=p_free;

    while(1)
    {
        if(NULL==p_free)
        {
            break;
        }


        if(key==p_free->data)
        {
            if(p_free==list->pnext)
            {
                list->pnext=p_free->pnext;//头结点指向的首结点更新为新的首结点(原第二个结点)
                free(p_free);
            }
            else
            {
                p_pre->pnext=p_free->pnext;
                free(p_free);
            }

            list->clen--;

            return 0;
        }
        else
        {
            p_pre=p_free;//待删除结点的前驱结点
            p_free=p_free->pnext;//待删除结点
        }
    }
    return 0;
}
2.11.4.2多结点删除
用于多个结点值相同的情况
/*==============删除单向链表中指定结点(多结点删除)===============*/
int pop_appointed_node(LABLE *list,int key)
{
    NODE *p_free=NULL;
    NODE *p_pre=NULL;
    int free_cnt=0;

    /*初始化遍历指针*/
    p_free=list->pnext;
    p_pre=p_free;

    while(1)
    {
        if(NULL==p_free)
        {
            break;
        }


        if(key==p_free->data)
        {
            if(p_free==list->pnext)
            {
                list->pnext=p_free->pnext;//头结点指向的首结点更新为新的首结点(原第二个结点)
                free(p_free);
            }
            else
            {
                p_pre->pnext=p_free->pnext;
                free(p_free);
            }

            list->clen--;
            p_free=p_pre->pnext;
            free_cnt++;//每删除一个相同值的结点,删除结点数+1
        }
        else
        {
            p_pre=p_free;//待删除结点的前驱结点
            p_free=p_free->pnext;//待删除结点
        }
    }

    return free_cnt;//返回删除的结点个数
}

2.12单向链表排序

2.12.1单向链表排序-插入排序法

举报

相关推荐

0 条评论