双向链表

image
image
image
image

/********************************************************************************************************
*
*
* 设计双向链表的接口
*
* 
*
* Copyright (c)  2023-2024   1523940xxxx@163.com   All right Reserved
* ******************************************************************************************************/



//指的是双向链表中的结点有效数据类型,用户可以根据需要进行修改
typedef int  DataType_t;

//构造双向链表的结点,链表中所有结点的数据类型应该是相同的
typedef struct DoubleLinkedList
{
	DataType_t  		     data; //结点的数据域
	struct DoubleLinkedList	*prev; //直接前驱的指针域
	struct DoubleLinkedList	*next; //直接后继的指针域

}DoubleLList_t;


//创建一个空双向链表,空链表应该有一个头结点,对链表进行初始化
DoubleLList_t * DoubleLList_Create(void)
{
	//1.创建一个头结点并对头结点申请内存
	DoubleLList_t *Head = (DoubleLList_t *)calloc(1,sizeof(DoubleLList_t));
	if (NULL == Head)
	{
		perror("Calloc memory for Head is Failed");
		exit(-1);
	}

	//2.对头结点进行初始化,头结点是不存储数据域,指针域指向NULL
	Head->prev = NULL;
	Head->next = NULL;

	//3.把头结点的地址返回即可
	return Head;
}

//创建新的结点,并对新结点进行初始化(数据域 + 指针域)


DoubleLList_t * DoubleLList_NewNode(DataType_t data)
{
	//1.创建一个新结点并对新结点申请内存
	DoubleLList_t *New = (DoubleLList_t *)calloc(1,sizeof(DoubleLList_t));
	if (NULL == New)
	{
		perror("Calloc memory for NewNode is Failed");
		return NULL;
	}

	//2.对新结点的数据域和指针域(2个)进行初始化
	New->data = data;
	New->prev = NULL;
	New->next = NULL;

	return New;
}
//头插
bool DoubleLList_HeadInsert(DoubleLList_t *Head,DataType_t data)
{
	//1.创建新的结点,并对新结点进行初始化
    DoubleLList_t *New = DoubleLList_NewNode(data);
    if(NULL == New)
    {
        printf("can not new node\n");
        return false;
    }
    //2.判断双向链表是否为空,如果为空,则直接插入到头结点之后
    if(NULL == Head->next)
    {
        Head->next = New;//让头结点的next指针指向新结点
        return true;
    }
    //3.如果双向链表为非空,则把新结点插入到链表的头部
    New->next = Head->next;//让新结点的next指针指向原本的首结点地址
	
    Head->next->prev = New;//原来的首结点的prev指针指向新结点的地址
    
	Head->next = New;//更新头结点的next指针,让next指针指向新结点的地址
	
    return true;
}
//尾插
bool DoubleLList_TailInsert(DoubleLList_t *Head,DataType_t data)
{
	DoubleLList_t *Phead = Head;//备份头结点地址,防止头结点丢失
	
	//1.创建新的结点,并对新结点进行初始化
    DoubleLList_t *New = DoubleLList_NewNode(data);
    if(NULL == New)
    {
        printf("can not new node\n");
        return false;
    }
    //2.判断双向链表是否为空,如果为空,则直接插入到头结点之后
    if(NULL == Head->next)
    {
        Head->next = New;//让头结点的next指针指向新结点
        return true;
    }
    //3.如果双向链表为非空,则把新结点插入到链表的尾部
    //要遍历,所以对头结点备份一下
	whlie(Phead->next)
	{
		Phead = Phead->next;
	}
	
	Phead->next = New;//尾结点的next指针指向新结点地址
	
	New->prev = Phead;//新结点的prev指针指向原本的尾结点的地址
	
	
    return true;
}

//指定位置插入
bool DoubleLList_DestInsert(DoubleLList_t *Head,DataType_t data)
{
	DoubleLList_t *Phead = Head;//备份头结点地址,防止头结点丢失
	
	//1.创建新的结点,并对新结点进行初始化
    DoubleLList_t *New = DoubleLList_NewNode(data);
    if(NULL == New)
    {
        printf("can not new node\n");
        return false;
    }
    //2.判断双向链表是否为空,如果为空,则直接插入到头结点之后
    if(NULL == Head->next)
    {
        Head->next = New;//让头结点的next指针指向新结点
        return true;
    }
	//3.如果双向链表尾为非空,此时分为3种情况(头部 or 尾部 or 中间)
	while(Phead->next)
	{
		Phead = Phead->next;
		if(Phead->data == destval)
		{
			break;
		}
	}
	//如果遍历链表之后发现没有目标结点,则退出即可
    if(Phead->next == NULL && Phead->data != destval)
	{
		printf("dest node is not fount\n");
		return false;
	}
	//如果遍历链表找到目标结点,则分为(头部 or 尾部 or 中间)
	//头部可以不用写
	if(Phead->next == NULL) //尾插
	{
		New->prev = Phead;//新结点的prev指针指向尾结点的地址
		Phead->next = New;//尾结点的next指针指向新结点
	}
	else
	{
		New->next = Phead->next;  //新结点的next指针指向目标结点的直接后继结点
		New->prev = Phead;        //新结点的prev指针指向目标结点的地址
		Phead->next->prev = New;  //目标结点的直接后继结点的prev指针指向新结点
		Phead->next = New;        //目标结点的next指针指向新结点
	}
	return true;
}
//指定删除
bool DoubleLList_DestDel(DoubleLList_t *Head,DataType_t data)
{
	DoubleLList_t *Phead = Head;//备份头结点地址,防止头结点丢失
	
	//1.判断双向链表是否为空,如果为空,则直接插入到头结点之后
    if(NULL == Head->next)
    {
        printf("linked list is empty\n");
        return false;
    }
	//2.如果双向链表尾为非空,此时遍历链表查找没有目标结点(找到 or 未找到)
	while(Phead->next)
	{
		Phead = Phead->next;
		
		if(Phead->data == destval)
		{
			break;
		}
	}
	}
	//如果遍历链表之后发现没有目标结点,则退出即可
    if(Phead->next == NULL && Phead->data != destval)
	{
		printf("dest node is not fount\n");
		return false;
	}
	//如果链表中找到目标结点,则分为(头部 or 尾部 or 中间)
	if(Phead == head->next)          //头部
	{
		Head ->next = Phead->next;   //更新头结点,让头结点的next指针指向首结点的直接后继
		
		if(Phead->next != NULL)
		{
			Phead->next->prev = NULL;
			Phead->next = NULL;
		}
		
		free(Phead);                 //释放待删除结点
	}
	else if(Phead->next == NULL)     //尾部
	{
		Phead ->prev->next = NULL;   //尾结点的直接前驱结点的next指针指向NULL
		Phead->prev = NULL;          //尾结点的prev指针指向NULL
		free(Phead);	
	}
	else                             //中间
	{
		Phead->prev->next = Phead->next;//让待删除结点的直接前驱结点的next指针指向待删除结点的直接后继地址
		Phead->next->prev = Phead->prev;//让待删除结点的直接后继结点的prev指针指向待删除结点的直接前驱地址
		Phead->next = NULL;             //让待删除结点的next指针指向NULL
		Phead->prev = NULL;             //让待删除结点的prev指针指向NULL
		free(Phead);                    //释放待删除结点
	}
	
	return ture;
}

int main(int argc, char const *argv[])
{
	
	return 0;
}
posted @ 2024-04-25 17:17  freeangel123  阅读(20)  评论(0)    收藏  举报