单向链表回环的判断可以用步长法
这个实现 : 选择单向链表中的任一节点, 遍历单向链表, 判断是否能回到同一节点.
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;
}