(有头节点循环)双链表的基本操作

我们对此分为三个文件,两个源文件DList.c  main.c 和一个头文件SList.h

DList.h 中用来包含头文件,定义结构体,和对函数的声明;DList.c 中写对函数的实现; main.c 中是主函数和测试函数

 

"DList.h"

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int DLDataType;

typedef struct DListNode {
	DLDataType val;
	struct DListNode *next;
	struct DListNode *prev;
}DListNode;

typedef struct DList {
	struct DListNode *head;
}DList;

// 内部接口
DListNode * BuyNode(DLDataType val);

// 初始化
void DListInit(DList * dlist);

// 清空(只是删除链表中有实际意义的节点。并没有删除头节点)
void DListClear(DList *dlist);

// 销毁(头结点都没有了,是个无效链表)
void DListDestroy(DList *dlist);


// 增删改查
// 在 pos 结点前面做插入
void DListInsert(DListNode *pos, DLDataType val);


// 头插
void DListPushFront(DList *dlist, DLDataType val);

// 尾插
void DListPushBack(DList *dlist, DLDataType val);

// 查找
// 找到第一个 val 的结点,返回结点地址
// 如果没找到,返回 NULL
DListNode * DListFind(DList *dlist, DLDataType val);

// 删除 pos 结点,pos 不是头结点
void DListErase(DListNode *pos);

//头删
void DListPopFront(DList *dlist);

//尾删
void DListPopBack(DList *dlist);

// 打印
void DListPrintByHead(DListNode *head);//传头节点地址打印

void DListPrintByDList(DList *dlist);//传链表地址打印

"DList.c"

#include"DList.h"

//创建节点
DListNode * BuyNode(DLDataType val)
{
	DListNode *node = (DListNode *)malloc(sizeof(DListNode));
	assert(node);
	node->val = val;
	node->next = node->prev = NULL;

	return node;
}

//链表初始化
void DListInit(DList * dlist)
{
	//创建头节点
	DListNode *head = BuyNode(0);// 头节点中val无意义(有时会被用来存放链表长度)
							 // 此处val是无意义,并没有存放链表长度
	head->next = head->prev = head;
	dlist->head = head;
}

//清空链表
void DListClear(DList *dlist)
{
	DListNode *cur, *next;
	for (cur = dlist->head->next; cur != dlist->head; cur = next)
	{
		next = cur->next;
		free(cur);
	}
	dlist->head->next = dlist->head->prev = dlist->head;
}

//销毁
void DListDestroy(DList *dlist)
{
	DListClear(dlist);

	// 指针free之后,free函数只是把指针指向的内存空间释放了,即内存中存储的值,
	// 但是并没有将指针的值赋为NULL,指针仍然指向这块内存。
	free(dlist->head);      
	dlist->head = NULL;
}

// 在 pos 结点前面做插入
void DListInsert(DListNode *pos, DLDataType val)
{
	//申请新节点
	DListNode *node = BuyNode(val);
	//插入
	node->prev = pos->prev;     
	node->next = pos;           
	pos->prev->next = node;      
	pos->prev = node;
}


// 头插
void DListPushFront(DList *dlist, DLDataType val)
{
	DListInsert(dlist->head->next, val);

#if 0
	//创建一个节点
	DListNode *node = BuyNode(val);
	//插入
	node->prev = dlist->head;
	node->next = dlist->head->next;
	dlist->head->next->prev = node;
	dlist->head->next = node;
#endif
}

// 尾插
void DListPushBack(DList *dlist, DLDataType val)
{
	DListInsert(dlist->head, val);

#if 0
	//创建一个节点
	DListNode *node = BuyNode(val);
	//插入
	node->prev = dlist->head->prev;
	node->next = dlist->head;
	dlist->head->prev->next = node;
	dlist->head->prev = node;
#endif
}

// 查找
//(找到第一个 val 的结点,返回结点地址; 如果没找到,返回 NULL)
DListNode * DListFind(DList *dlist, DLDataType val)
{
	assert(dlist->head);
	for (DListNode *cur = dlist->head->next; cur != dlist->head; cur = cur->next)
	{
		if (cur->val == val)
		{
			return cur;
		}
	}
	return NULL;
}

// 删除 pos 结点,pos 不是头结点
void DListErase(DListNode *pos)
{
	assert(pos);
	pos->prev->next = pos->next;
	pos->next->prev = pos->prev;
	free(pos);
}

void DListPopFront(DList *dlist)
{
	assert(dlist->head->next != dlist->head);

	DListErase(dlist->head->next);
}

void DListPopBack(DList *dlist)
{
	assert(dlist->head->next != dlist->head);

	DListErase(dlist->head->prev);
}

// 打印
void DListPrintByHead(DListNode *head)//传头节点地址打印
{
	assert(head);
	for (DListNode *cur = head->next; cur != head; cur = cur->next)
	{
		printf("%d->",cur->val);
	}
	printf("\n");
}

void DListPrintByDList(DList *dlist)//传链表地址打印
{
	assert(dlist);
	assert(dlist->head);
	DListPrintByHead(dlist->head);
}

"main.c"

#include"DList.h"


void test()
{
	DList dlist;

	DListInit(&dlist);
	//DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);

	//printf("%p", DListFind(&dlist, 0));
	DListPushFront(&dlist, 3);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);
	DListPushFront(&dlist, 2);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);
	DListPushFront(&dlist, 1);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);

	DListPushBack(&dlist, 11);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);
	DListPushBack(&dlist, 12);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);
	DListPushBack(&dlist, 13);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);

	DListNode *pos = DListFind(&dlist, 2);
	DListErase(pos);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);

	DListNode *pos1 = DListFind(&dlist, 3);
	DListInsert(pos1, 2);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);

	DListPopFront(&dlist);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);
	DListPopFront(&dlist);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);
	DListPopFront(&dlist);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);

	DListPopBack(&dlist);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);
	DListPopBack(&dlist);
	DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);


	DListClear(&dlist);
	//DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);

	DListDestroy(&dlist);
	//DListPrintByDList(&dlist);
	//DListPrintByHead(dlist.head);
}

int main()
{
	test();
	system("pause");
	return 0;
}

以上"main.c"中为个人的测试代码,可以根据自己的喜好设置测试代码,这里给出测试代码仅供参考。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值