No.31 我与代码的日常:链表的基本操作(双向+带头+循环)

学习不易,需要坚持。

//DList.h
#pragma once


typedef int DLDataType ;

typedef struct DListNode
{
	//结点
	DLDataType val ;
	struct DListNode* next ;
	struct DListNode* prev ;
}DListNode ;

typedef struct
{
	//双链表类型
	DListNode* head ;
}DList ;

//内部接口,申请新结点
DListNode* BuyNode(DLDataType val) ;

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

//清空
void DListClear(DList* dlist) ;

//销毁(销毁后为无效链表,注意与“清空”区分)
void DListDestroy(DList* dlist) ;

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

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

//在pos结点前做插入
void DListInsert(DListNode* pos,DLDataType val) ;

//打印
void DListPrintByDList(DList* dlist) ;


//查找并返回某结点的地址
DListNode* DListFind(DList* dlist, DLDataType val) ;

//删除pos位置的点(非头)
void DListErase(DListNode* pos) ;

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

//尾删
void DListPopBack(DList* dlist) ;
//DList.c
#include "DList.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.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) ;
	assert(head) ;
	head->next = head ;
	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 ;
	dlist->head->prev = dlist->head ;
}

//销毁(销毁后为无效链表,注意与“清空”区分)
void DListDestroy(DList* dlist) 
{
	DListClear(dlist) ;
	free(dlist->head) ;
	dlist->head = NULL ; //连头都没有了,为无效链表
}

//头插
void DListPushFront(DList* dlist, DLDataType val)
{
	//申请空间
	DListNode* node = BuyNode(val) ;
	//处理next,prev,4个指针要变
	node->prev = dlist->head ;
	node->next = dlist->head->next ;
	dlist->head->next->prev = node ;
	dlist->head->next = node ;
}

//尾插
void DListPushBack(DList* dlist, DLDataType val)
{
	//申请空间
	DListNode* node = BuyNode(val) ;
	node->prev = dlist->head->prev;
	node->next = dlist->head ;
	dlist->head->prev->next = node ;
	dlist->head->prev = node ;
}

//打印
void DListPrintByDList(DList* dlist) 
{
	DListNode* cur ;
	for(cur=dlist->head->next; cur!=dlist->head; cur=cur->next)
	{
		printf("%d-->",cur->val) ;
	}
	printf("\n") ;
}

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

//查找并返回某结点的地址
DListNode* DListFind(DList* dlist, DLDataType val)
{
	DListNode* cur ;
	for(cur=dlist->head->next; cur!=dlist->head; cur=cur->next)
	{
		if(cur->val == val)
		{
			return cur ;
		}
	}
	return NULL ;
}

//删除pos位置的点(非头)
void DListErase(DListNode* 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) ;
}
//Main.c
#include "DList.h"
#include <stdio.h>

int main()
{
	DList dlist ;
	DListNode* pos ;

	DListInit(&dlist) ;

	printf("头插:\n") ;
	DListPushFront(&dlist, 3) ;
	DListPushFront(&dlist, 2) ;
	DListPushFront(&dlist, 1) ;
	DListPrintByDList(&dlist) ;

	printf("\n尾插:\n") ;
	DListPushBack(&dlist, 8) ;
	DListPushBack(&dlist, 9) ;
	DListPushBack(&dlist, 10) ;
	DListPrintByDList(&dlist) ;

	printf("\n在pos之前插入:\n") ;
	pos = DListFind(&dlist, 8) ;
	DListInsert(pos,1024) ;
	DListPrintByDList(&dlist) ;

	printf("\n删除pos位置的值:\n") ;
	DListErase(pos) ;
	DListPrintByDList(&dlist) ;

	printf("\n头删:\n") ;
	DListPopFront(&dlist) ;
	DListPrintByDList(&dlist) ;

	printf("\n尾删:\n") ;
	DListPopBack(&dlist) ;
	DListPrintByDList(&dlist) ;

	printf("\n") ;
	return 0 ;
}

运行结果:在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章