单向链表回环的判断可以用步长法
这个实现 : 选择单向链表中的任一节点, 遍历单向链表, 判断是否能回到同一节点.
demo:
/// 建立链表 CreateList(&pNode, 6); ///< 建立拥有N个节点的单向链表 ShowList(&pNode); /// 判断单向链表是否回环 DbgPrint("List loop is %ws\n", (TRUE == FindLoop(pNode)) ? L"TRUE" : L"FALSE"); /// 释放链表 RemoveList(&pNode); ShowList(&pNode);
/// @file Function.h /// @brief 功能的实现 #ifndef __FUNCTION_H__ #define __FUNCTION_H__ #include <ntddk.h> typedef struct _node { int data; struct _node *next; } NODE,*PNODE; ///< 外部接口 int FindLoop(NODE * head); /// 内部接口 void CreateList(PNODE * ppNode, size_t nListSize); void RemoveList(PNODE * ppNode); void ShowList(PNODE * ppNode); BOOLEAN IsListLoop(PNODE * ppNode); #endif
/// @file Function.c /// @brief 功能的实现 #include "Function.h" void CreateList(PNODE * ppNode, size_t nListSize) { PNODE pNodeHead = NULL; PNODE pNodeCur = NULL; size_t nIndex = 0; if ((NULL == ppNode) || (NULL != *ppNode) || (nListSize < 1)) { return; } pNodeHead = (PNODE)ExAllocatePool(NonPagedPool, sizeof(NODE)); pNodeHead->data = 0; pNodeHead->next = NULL; *ppNode = pNodeHead; pNodeCur = pNodeHead; for (nIndex = 1; nIndex < nListSize; nIndex++) { pNodeCur->next = (PNODE)ExAllocatePool(NonPagedPool, sizeof(NODE)); pNodeCur = pNodeCur->next; pNodeCur->data = nIndex; pNodeCur->next = NULL; } pNodeCur->next = pNodeHead; ///< 形成单链表回环 } void ShowList(PNODE * ppNode) { PNODE pNodeCur = NULL; PNODE pNodeHead = NULL; if ((NULL == ppNode) || (NULL == *ppNode)) { DbgPrint("ppNode is invalid\n"); return; } pNodeHead = *ppNode; DbgPrint("pNodeHead = 0x%p, pNodeHead->data = 0x%x, pNodeHead->next = 0x%p\n", pNodeHead, pNodeHead->data, pNodeHead->next); pNodeCur = pNodeHead->next; while ((NULL != pNodeCur) && (pNodeCur != pNodeHead)) { DbgPrint("pNodeCur = 0x%p, pNodeCur->data = 0x%x, pNodeCur->next = 0x%p\n", pNodeCur, pNodeCur->data, pNodeCur->next); pNodeCur = pNodeCur->next; } } void RemoveList(PNODE * ppNode) { PNODE pNodeHead = NULL; PNODE pNodeCur = NULL; PNODE pNodeNext = NULL; if ((NULL == ppNode) || (NULL == *ppNode)) { return; } pNodeHead = *ppNode; /// 释放头节点之外的数据 pNodeCur = pNodeHead->next; while ((NULL != pNodeCur) && (pNodeCur != pNodeHead)) { pNodeNext = pNodeCur->next; ExFreePool(pNodeCur); pNodeCur = pNodeNext; } /// 释放头节点 ExFreePool(pNodeHead); *ppNode = NULL; } BOOLEAN IsListLoop(PNODE * ppNode) { BOOLEAN bFind = FALSE; PNODE pNodeCur = NULL; PNODE pNodeHead = NULL; if ((NULL == ppNode) || (NULL == *ppNode)) { DbgPrint("ppNode is invalid\n"); return FALSE; } pNodeHead = *ppNode; pNodeCur = pNodeHead->next; while (NULL != pNodeCur) { if (pNodeCur == pNodeHead) { bFind = TRUE; break; } pNodeCur = pNodeCur->next; } return bFind; } int FindLoop(NODE * head) { if (NULL == head) { return FALSE; } return IsListLoop(&head); }
/// @file sys.c /// @brief 驱动主程序 #include <ntddk.h> #include "Function.h" #define MODULE_NAME L"DrvDemo" #define DRIVER_NAME MODULE_NAME L".sys" #define DEVICE_NAME_GLOBAL L"\\\\.\\" MODULE_NAME #define DEVICE_NAME L"\\device\\" MODULE_NAME #define LINK_NAME L"\\dosDevices\\" MODULE_NAME NTSTATUS DispatchCommon(PDEVICE_OBJECT pDeviceObject, PIRP pIrp); VOID DriverUnload(PDRIVER_OBJECT pDriverObject); NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegPath) { size_t nIndex = 0; NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_OBJECT pDeviceObject = NULL; UNICODE_STRING ustrDeviceName = {0}; UNICODE_STRING ustrLinkName = {0}; PNODE pNode = NULL; DbgPrint(">> DriverEntry\r\n"); RtlInitUnicodeString(&ustrDeviceName, DEVICE_NAME); RtlInitUnicodeString(&ustrLinkName, LINK_NAME); ntStatus = IoCreateDevice( pDriverObject, 0, &ustrDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); if (!NT_SUCCESS(ntStatus)) { DbgPrint("<< DriverEntry : error IoCreateDevice\r\n"); return ntStatus; } pDeviceObject->Flags |= DO_BUFFERED_IO; ntStatus = IoCreateSymbolicLink( &ustrLinkName, &ustrDeviceName); if (!NT_SUCCESS(ntStatus)) { DbgPrint("<< DriverEntry : error IoDeleteDevice\r\n"); IoDeleteDevice(pDeviceObject); return ntStatus; } for(nIndex = 0; nIndex < IRP_MJ_MAXIMUM_FUNCTION; nIndex++) { pDriverObject->MajorFunction[nIndex] = DispatchCommon; } pDriverObject->DriverUnload = DriverUnload; /// 建立链表 CreateList(&pNode, 6); ///< 建立拥有N个节点的单向链表 ShowList(&pNode); /// 判断单向链表是否回环 DbgPrint("List loop is %ws\n", (TRUE == FindLoop(pNode)) ? L"TRUE" : L"FALSE"); /// 释放链表 RemoveList(&pNode); ShowList(&pNode); DbgPrint("<< DriverEntry\r\n"); return STATUS_SUCCESS; } VOID DriverUnload(PDRIVER_OBJECT pDriverObject) { UNICODE_STRING ustrLinkName = {0}; DbgPrint(">> DriverUnload\r\n"); RtlInitUnicodeString(&ustrLinkName, LINK_NAME); IoDeleteDevice(pDriverObject->DeviceObject); IoDeleteSymbolicLink(&ustrLinkName); DbgPrint("<< DriverUnload\r\n"); } NTSTATUS DispatchCommon(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; }