双链表C语言实现

双链表C语言实现

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

/*声明描述节点信息的结构体*/
typedef struct node {
    int data; //数据
    struct node *next; //指向下一个节点
    struct node *prev; //指向上一个节点
}node_t;

/*声明描述整个链表的结构体*/
typedef struct list {
    struct node head; //头节点
    struct node tail; //尾节点
}list_t;

/*定义初始化链表函数*/
/*空链表:head和tail连起来*/
void list_init(list_t *list)
{
    list->head.next = &list->tail; //头指向尾
    list->tail.prev = &list->head; //尾指向头
    list->head.prev = NULL;
    list->tail.next = NULL;
}

/*判断链表是否为空*/
int list_empty(list_t *list)
{
    return list->head.next == &list->tail; //空返回1,非空返回0
}

/*获取链表节点个数*/
int list_size(list_t *list)
{
    int count = 0; //计数
    for(node_t *pnode = &list->head; 
            pnode != &list->tail;
            	pnode = pnode->next) {
        node_t *pfirst = pnode;
        node_t *pmid = pfirst->next;
        node_t *plast = pmid->next;
        if(pmid != &list->tail)
            count++; //只要没有到tail,加一个
    }
    return count;
}

//定义创建节点函数
static node_t *create_node(int data)
{
    //给节点分配内存
    node_t *p = (node_t *)malloc(sizeof(node_t));
    //初始化节点
    p->next = NULL;
    p->prev = NULL;
    p->data = data;
    return p;
}

//定义将新节点插入pfirst和pmid之间
static void insert_data(node_t *pfirst, node_t *pmid, node_t *pnode)
{
    //将新节点插入pfirst和pmid之间
    pfirst->next = pnode;
    pnode->prev = pfirst;
    pnode->next = pmid;
    pmid->prev = pnode;
}

/*后插*/
void list_add_tail(list_t *list, int data)
{
    //创建新节点
    node_t *pnode = create_node(data); 
    //定义游标:随意定游标,这个代码仅仅参考
    node_t *pfirst = list->tail.prev; //pfirst指向最后一个节点
    node_t *pmid = pfirst->next; //pmid指向tail
    node_t *plast = pmid->next; //plast指向NULL
    //插入
    insert_data(pfirst, pmid, pnode);
}

/*前插*/
void list_add_head(list_t *list, int data)
{
    //创建新节点
    node_t *pnode = create_node(data); 
    //定义游标 
    node_t *pfirst = &list->head; //pfirst指向head
    node_t *pmid = pfirst->next; //pmid指向第一个节点
    node_t *plast = pmid->next; //plast指向第二个节点
    //插入
    insert_data(pfirst, pmid, pnode);
}

/*由小到大插*/
void list_add(list_t *list, int data)
{
    //1.创建新节点
    node_t *pnode = create_node(data);
    //2.遍历
    for(node_t *ptmp = &list->head; 
            ptmp != &list->tail;
            	ptmp = ptmp->next) {
        //3.游标
        node_t *pfirst = ptmp;
        node_t *pmid = pfirst->next;
        node_t *plast = pmid->next;
        //4.将新节点同样插入到pfirst和pmid之间
        if(pmid->data > pnode->data || pmid == &list->tail) {
            insert_data(pfirst, pmid, pnode); //插入
            break;
        }
    }
}

//删除节点
static void del_data(node_t *pfirst, node_t *pmid, node_t *plast)
{
    //1.连接pfirst和plast,干掉pmid
    pfirst->next = plast;
    plast->prev = pfirst;

    //2.释放pmid的内存
    free(pmid);
    pmid = NULL;
}

/*删除最后一个节点*/
void list_del_tail(list_t *list)
{
    //1.判断是否空链表
    if(list->head.next == &list->tail) {
        printf("list is empty.\n");
        return;
    }

    //2.定义游标
    node_t *plast = &list->tail; //plast指向tail
    node_t *pmid = plast->prev; //pmid指向最后一个节点
    node_t *pfirst = pmid->prev; //pfirst指向倒数第二个节点

    //3.删除数据
    del_data(pfirst, pmid, plast);
}

/*删除第一个节点*/
void list_del_head(list_t *list)
{
    /*1.判断链表是否为空*/
    if(list_empty(list)) {
        printf("list is empty.\n");
        return;
    }

    //2.定义游标
    node_t *pfirst = &list->head; //pfirst指向头节点
    node_t *pmid = pfirst->next; //pmid指向第一个节点
    node_t *plast = pmid->next; //plast指向第二个节点

    //3.删除数据
    del_data(pfirst, pmid, plast);
}

/*删除某个数字所在的节点*/
void list_del(list_t *list, int data)
{
    //通过data遍历遍历找到要删除的节点pmid
    for(node_t *pnode = &list->head; 
            pnode != &list->tail;
            	pnode=pnode->next) {
        node_t *pfirst = pnode;
        node_t *pmid = pfirst->next;
        node_t *plast = pmid->next;
        if(pmid->data == data && pmid != &list->tail) {
            //删除数据
            del_data(pfirst, pmid, plast);
            return;
        }
    }
    printf("the data isn't exist\n");
}

/*获取最后一个节点的数据并返回*/
int list_get_tail(list_t *list)
{
    //判断链表是否为空
    if(list_empty(list))
        return -1;

    //定义游标
    node_t *plast = &list->tail; //plast指向tail
    node_t *pmid = plast->prev; //pmid指向最后一个节点
    node_t *pfirst = pmid->prev; //pfirst指向倒数第二个节点

    //返回pmid指向的最后一个节点中的数据
    return pmid->data;
}

/*获取第一个节点的数据并返回*/
int list_get_head(list_t *list)
{
    //判断链表是否为空
    if(list_empty(list))
        return -1;

    //定义游标
    node_t *pfirst = &list->head; //pfirst指向head
    node_t *pmid = pfirst->next; //pmid指向第一个节点
    node_t *plast = pmid->next; //pfirst指向第二个节点

    //返回pmid指向的第一个节点中的数据
    return pmid->data;
     
}

/*根据节点编号获取对应的数据*/
int list_get(list_t *list, int index)
{
    //1.计数
    int count = 0;

    //2.找节点
    for(node_t *pnode = &list->head;
            pnode != &list->tail;
            	pnode=pnode->next) {
        //3.定义游标
        node_t *pfirst = pnode;
        node_t *pmid = pfirst->next;
        node_t *plast = pmid->next;
        //4.判断count和index
        if(count == index && pmid != &list->tail) {
            return pmid->data;
        }
        count++;
    }
    return -1; //没有找到
}
/*打印链表所以数据*/
void list_show(list_t *list)
{
	if(list_empty(list)){
		printf("list is empty\n");
		return;
	}
	for(node_t *pnode = &list->head;
			pnode != &list->tail;
				pnode = pnode->next){
		node_t *pfirst = pnode;
		node_t *pmid = pfirst->next;
		node_t *plast = pmid->next;
		if(pmid != &list->tail)
			printf("%d ",pmid->data);
	}
	putchar('\n');
}
/*清理链表*/
void list_deinit(list_t *list)
{
    while(list->head.next != &list->tail) {
        //定义游标
        node_t *pfirst = &list->head;
        node_t *pmid = pfirst->next;
        node_t *plast = pmid->next;
        
        //先连接pfirst和plast
        pfirst->next = plast;
        plast->prev = pfirst;

        //干掉pmid节点的内存
        free(pmid);
        pmid = NULL;
    }
}

//测试代码
void main(int argc,char *argv[])
{
	//1.定义链表变量l
	list_t list;

	//2.链表初始化
	list_init(&list);

	//3.头插法添加链表结点
	list_add_head(&list,30);
	list_add_head(&list,20);
	list_add_head(&list,10);

	//4.尾插法添加链表结点
	list_add_tail(&list,40);
	list_add_tail(&list,50);
	list_add_tail(&list,60);
	//打印链表所有结点数据
	list_show(&list);	

	//5.判断链表是否为空
	if(list_empty(&list)){
		printf("list is empty\n");
	}

	//6.获取链表结点个数
	printf("the size of list is %d\n",list_size(&list));

	//7.从小到大插入到链表中
	list_add(&list,45);
	//打印链表所有结点数据
	list_show(&list);	

	//8.删除第一个结点
	list_del_head(&list);
	//打印链表所有结点数据
	list_show(&list);	

	//9.删除最后一个结点
	list_del_tail(&list);
	//打印链表所有结点数据
	list_show(&list);

	//10.删除某个数据所在结点
	list_del(&list,45);
	//打印链表所有结点数据
	list_show(&list);

	//11.获取第一个结点的数据
	printf("the data in first is %d\n",list_get_head(&list));

	//12.获取最后一个结点的数据
	printf("the data in end is %d\n",list_get_tail(&list));

	//13.通过结点编号获取结点数据(-1时表示给定结点编号错误)
	printf("the appointed node number data is %d\n",list_get(&list,0));

	//14.清理链表
	list_deinit(&list);
	//打印链表所有结点数据
	list_show(&list);
	return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值