带头结点双向循环链表的C语言实现

目录

1 功能介绍

2 头文件内容

3 头文件内容实现

4 测试用主函数

1 功能介绍

  • 双向链表销毁
  • 双向链表打印
  • 双向链表尾插
  • 双向链表尾删
  • 双向链表头插
  • 双向链表头删
  • 双向链表查找
  • 双向链表在pos位置前插入元素
  • 双向链表删除pos位置结点

2 头文件内容

#ifndef _DList_H
#define _DList_H

#include
#include
#include

typedef int LTDataType;
typedef struct ListNode
{
	LTDataType _data;
	struct ListNode* next;  // 指向下一个结点
	struct ListNode* prev;  // 指向前一个结点
}ListNode;


//初始化
void ListInit(ListNode** head);

//双向链表销毁
void ListDestory(ListNode* plist);

//双向链表打印
void ListPrint(ListNode* plist);

//双向链表大小
int ListSize(ListNode* head);

//双向链表判空
int ListEmpty(ListNode* head);

//双向链表尾插
void ListPushBack(ListNode* plist, LTDataType x);

//双向链表尾删
void ListPopBack(ListNode* plist);

//双向链表头插
void ListPushFront(ListNode* plist, LTDataType x);

//双向链表头删
void ListPopFront(ListNode* plist);

//双向链表查找
ListNode* ListFind(ListNode* plist, LTDataType x);

//双向链表在pos位置前插入元素
void ListInsert(ListNode* pos, LTDataType x);

//双向链表删除pos位置结点
void ListErase(ListNode* pos);

#endif

3 头文件内容实现

 

#include"DList.h"

//创建新结点
ListNode* BuyListNode(LTDataType x)
{
	ListNode* newNode = (ListNode*)malloc(sizeof(LTDataType));
	if (NULL == newNode){
		printf("开辟新结点失败\n");
		return NULL;
	}
	newNode->_data = x;
	newNode->next = NULL;
	newNode->prev = NULL;
	return newNode;
}

//初始化
void ListInit(ListNode** head)
{
	if (head == NULL){
		return;
	}

	*head = BuyListNode(0);
	(*head)->next = *head;//让头节点的指向循环起来
	(*head)->prev = *head;
}

//双向链表销毁
void ListDestory(ListNode* head){

	//创造创建新节点位于链表起始位置,准备遍历链表清空节点
	ListNode* cur = head->next;

	//清空链表中节点
	while (cur != head){
		head->next = cur->next;//保存下一位节点
		free(cur);//释放该节点
		cur = cur->next;
	}

	//清理头节点
	free(head);
	head = NULL;
}

//双向链表打印
void ListPrint(ListNode* head){

	//创造创建新节点位于链表起始位置,准备遍历链表打印节点
	ListNode* cur = head->next;

	//打印链表中节点
	while (cur != head){
		printf("%d ", cur->_data);
		cur = cur->next;
	}
}

//双向链表大小
int ListSize(ListNode* head){

	//创建新节点和计数器位于链表起始位置,准备遍历链表进行计数
	ListNode* cur = head->next;
	int count = 0;

	//遍历链表
	while (cur != head){
		cur = cur->next;
		count++;
	}

	//遍历完成之后返回计数器
	return count;
}

//双向链表判空
int ListEmpty(ListNode* head){

	assert(head);
	// 若头节点指向自身说明链表中不存在内容,即链表为空返回1
	return head->next == head;
}

//双向链表尾插
void ListPushBack(ListNode* head, LTDataType x){

	//链表的尾插就相当于头节点之前插入元素
	ListInsert(head, x);
}

//双向链表尾删
void ListPopBack(ListNode* head){

	//保证链表不为空方可尾删
	if (ListEmpty(head)){
		return;
	}

	//链表的首元素是头节点的下一位指向
	ListErase(head->next);
}

//双向链表头插
void ListPushFront(ListNode* head, LTDataType x){

	//链表头插就相当于在头节点的后一个节点前插入元素
	ListInsert(head->next, x);
}

//双向链表头删
void ListPopFront(ListNode* head){

	//保证链表不为空方可头删
	if (ListEmpty(head)){
		return;
	}

	//链表的首元素是头节点的上一位指向
	ListErase(head->prev);
}

//双向链表查找
ListNode* ListFind(ListNode* head, LTDataType x){

	//创建新节点位于链表起始位置,准备遍历链表查找元素
	ListNode* cur = head->next;

	//遍历链表
	while (cur != head){
		if (cur->_data == x){
			return cur;
		}
		cur = cur->next;
	}

	//遍历未返回元素则节点中不存在元素x
	return NULL;
}

//双向链表在pos位置前插入元素
void ListInsert(ListNode* pos, LTDataType x){

	//判断插入位置pos的合法性
	if (pos == NULL){
		return;
	}

	//1.根据插入元素x创建新节点
	ListNode* newNode = BuyListNode(x);

	//2.先将新节点连接到pos之前(防止节点丢失)
	newNode->next = pos;
	newNode->prev = pos->prev;

	//3.断开原两节点之间的连接
	newNode->prev->next = newNode;
	pos->prev = newNode;
	
}

//双向链表删除pos位置结点
void ListErase(ListNode* pos){

	//判断删除位置pos的合法性
	if (pos == NULL){
		return;
	}

	//1.让pos位置的前后节点互相指向
	pos->prev->next = pos->next;
	pos->next->prev = pos->prev;

	//2.释放资源
	free(pos);
}

4 测试用主函数

int main()
{
	ListNode* head = NULL;
	ListInit(&head);

	if (ListEmpty(head) == 1){
		printf("链表为空\n");
	}

	ListPushFront(head, 1);
	ListPushFront(head, 2);
	ListPushFront(head, 3);
	ListPrint(head);
	printf("\n");
	printf("Size==%d\n", ListSize(head));

	ListPushBack(head, 4);
	ListPushBack(head, 5);
	ListPushBack(head, 6);
	ListPrint(head);
	printf("\n");
	printf("Size==%d\n", ListSize(head));
	return 0;
}

你可能感兴趣的:(链表,c语言,数据结构)