数据结构---双向链表

单向链表在之前的队列和stack中有使用到,这里画一下双向链表的模型:

头插法:

移除某个节点:

相关代码如下:

dlist.c

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



stDlistHead_t* dlist_init(void)
{
    stDlistHead_t *dlist = (stDlistHead_t *)malloc(sizeof(stDlistHead_t));
    if(dlist == NULL) {
        return NULL;
    }
	dlist->size = 0;
	dlist->head = NULL;
	dlist->tail = NULL;
	return dlist;
}

void dlist_destory(stDlistHead_t *dlist)
{
	stDlistNode_t *pNode = NULL;
	
	while(dlist->size > 0)
	{
		pNode = dlist->head;
		dlist->head = dlist->head->next;
		free(pNode);
		dlist->size--;
	}

    free(dlist);
    dlist = NULL;
    printf("list was destoried\n");
	return;
}

int dlist_insert_head(stDlistHead_t *dlist ,int data)
{
    stDlistNode_t *pNode = (stDlistNode_t *)malloc(sizeof(stDlistNode_t));
   if(pNode == NULL) {
		return -1;
    }

    pNode->data = data;			
	pNode->prev = NULL;
	pNode->next = NULL;

	if (dlist->size == 0) {
		dlist->head = pNode;
		dlist->tail = pNode;
	} else {
		pNode->next = dlist->head;
		dlist->head->prev = pNode;
		dlist->head = pNode;			
	}

	dlist->size++;
	return 0;
}

stDlistNode_t * dlist_remove_tail(stDlistHead_t *dlist)
{
	stDlistNode_t *pNode = NULL;

	if(dlist->size == 0) {
		return NULL;
	}

    pNode = dlist->tail;
	if(dlist->size > 1) {
		dlist->tail = dlist->tail->prev;
		dlist->tail->next = NULL;
	} else {
		dlist->head = NULL;
		dlist->tail = NULL;
	}
	dlist->size--;
	return pNode;
}

void dlist_remove_node(stDlistHead_t * dlist,stDlistNode_t *pNode)
{
	if ((dlist == NULL) || (pNode == NULL)) {
		return;
	}

	if (dlist->head == pNode) {
		dlist->head = dlist->head->next;
        dlist->head->prev = NULL;
	} else if (dlist->tail == pNode) {
		dlist->tail = pNode->prev;
		dlist->tail->next = NULL;
	} else {
		pNode->prev->next = pNode->next;
		pNode->next->prev = pNode->prev;
	}
	dlist->size--;
	pNode->prev = NULL;
	pNode->next = NULL;
	
	if (dlist->size == 0) {
        if(dlist != NULL) {
            free(dlist);
            dlist = NULL;
        }
	}
	return;
}
stDlistNode_t * dlist_search(stDlistHead_t * dlist,int data)
{
	stDlistNode_t *pNode = dlist->head;
	while(pNode != NULL) {
		if (pNode->data == data) {
			return pNode;
		}
		pNode = pNode->next;
    }
	return NULL;
}

void dlist_dump(stDlistHead_t *dlist)	
{
	int no = 0;
	stDlistNode_t *pNode = dlist->head;
	while(pNode != NULL) {
		printf("[%d] = %d\n",no++,pNode->data);
		pNode = pNode->next;
	}

	return;
}
int main()
{
	stDlistHead_t *dlist = {0};
    stDlistNode_t * pNode = NULL;

	dlist = dlist_init();

	printf("inset 0,1,2,3,4\n");
    for(int i=0; i < 5; i++) {
        dlist_insert_head(dlist, i);
    }
	dlist_dump(dlist);

    printf("remove the tail\n ");
	pNode = dlist_remove_tail(dlist);
	if(pNode != NULL) {
		printf("remove %d\n",pNode->data);
	}
    printf("insert 5\n");
	dlist_insert_head(dlist, 5);
	dlist_dump(dlist);

    printf("find 3\n");
    pNode = dlist_search(dlist, 3);
    if(pNode != NULL) {
        printf("found and delete\n");
        dlist_remove_node(dlist, pNode);
    }
    dlist_dump(dlist);
    dlist_destory(dlist);
    return 0;
}

list.h

#ifndef DLIST_H_
#define DLIST_H_
typedef struct DlistNode          //双向链表中每一个节点
{				  	
	struct DlistNode *prev;   //节点前项指针
	struct DlistNode *next;   //节点后项指针
	int    data;              //数据
}stDlistNode_t;

typedef struct Dlisthead          //定义链表总体
{
	int size;                 //链表长度
	stDlistNode_t *head;        //头指针
	stDlistNode_t *tail;        //尾部指针
}stDlistHead_t;


stDlistHead_t* dlist_init(void);
void dlist_destory(stDlistHead_t *dlist);
int dlist_insert_head(stDlistHead_t *dlist ,int data);
stDlistNode_t * dlist_remove_tail(stDlistHead_t *dlist);
void dlist_remove_node(stDlistHead_t * dlist,stDlistNode_t *pNode);
stDlistNode_t * dlist_search(stDlistHead_t * dlist,int data);
void dlist_dump(stDlistHead_t *dlist);

#endif

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值