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 ;
}

運行結果:在這裏插入圖片描述

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