您的位置:首页 > 其它

alg : 单向链表逆序 on drv

2013-05-29 18:19 309 查看
算法参考: http://blog.sina.com.cn/s/blog_4c1934d5010093ky.html
算法的思路:

遍历原始链表, 摘出每个元素, 作为新链表的头节点. 上一次摘出的原始链表元素作为本次摘出元素的Next节点.

当遍历完原始链表后, 新的链表就是逆序的单向链表.

我考虑了单向链表为回环的情况, 在驱动层实现了一次.

实验过了, 回环和非回环单向链表逆序都正常.

单链表逆向的实现:

BOOLEAN ListReverse(PNODE * ppNodeHead)
{
    BOOLEAN bListIsLoop     =   FALSE;
    size_t  nElementsCnt    =   0;
    PNODE   pNodeCur        =   NULL;   ///< 当前链表节点
    PNODE   pNodeNext       =   NULL;   ///< 下一链表节点
    PNODE   pNodeTail       =   NULL;

    PNODE   pListNewHead    =   NULL;
    PNODE   pListNewTail    =   NULL;

    NT_ASSERT(NULL != ppNodeHead);
    NT_ASSERT(NULL != *ppNodeHead);

    /// 计算单向链表的元素个数N, 可以使此链表逆序算法适用于链表"回环"或"不回环"的情况
    bListIsLoop = IsListLoop(ppNodeHead, &nElementsCnt, &pNodeTail);   ///< 不关心链表是否回环, 只需要链表元素个数
    if (nElementsCnt <= 1)
        return TRUE;    ///< 链表节点2个以上, 才需要逆序

    /// 遍历原始链表, 摘出每个元素, 作为新列表的头节点
    /// 返回的头节点是最后一个元素

    pNodeCur = *ppNodeHead;
    do 
    {
        pNodeNext = pNodeCur->pNext;
        if (NULL == pListNewHead)
        {
            /// 新List的尾节点是原始List的头节点
            pListNewTail = pNodeCur;
            pListNewTail->pNext = NULL;
            pListNewHead = pListNewTail;
        }
        else
        {
            pNodeCur->pNext = pListNewHead;
            pListNewHead = pNodeCur;
        }

        pNodeCur = pNodeNext;
        ShowList(&pListNewHead);
    } while (nElementsCnt-- > 1);

    if (bListIsLoop)
        pListNewTail->pNext = pListNewHead; ///< 处理回环情况

    *ppNodeHead = pListNewHead;
    ShowList(&pListNewHead);
    return TRUE;
}


运行结果

>> DriverEntry 
======================================== 
ShowList >> pNodeHead = 0x8674E930 
  pNodeHead->data = 0x0, pNodeHead->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85E96AB8
  pNodeCur = 0x85E96AB8, pNodeCur->data = 0x3, pNodeCur->pNext = 0x8690CE00
  pNodeCur = 0x8690CE00, pNodeCur->data = 0x4, pNodeCur->pNext = 0x86529190
  pNodeCur = 0x86529190, pNodeCur->data = 0x5, pNodeCur->pNext = 0x8674E930
======================================== 
ShowList >> pNodeHead = 0x8674E930 
  pNodeHead->data = 0x0, pNodeHead->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x85F0D8B8 
  pNodeHead->data = 0x1, pNodeHead->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x86C31548 
  pNodeHead->data = 0x2, pNodeHead->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x85E96AB8 
  pNodeHead->data = 0x3, pNodeHead->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x8690CE00 
  pNodeHead->data = 0x4, pNodeHead->pNext = 0x85E96AB8
  pNodeCur = 0x85E96AB8, pNodeCur->data = 0x3, pNodeCur->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x86529190 
  pNodeHead->data = 0x5, pNodeHead->pNext = 0x8690CE00
  pNodeCur = 0x8690CE00, pNodeCur->data = 0x4, pNodeCur->pNext = 0x85E96AB8
  pNodeCur = 0x85E96AB8, pNodeCur->data = 0x3, pNodeCur->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x86529190 
  pNodeHead->data = 0x5, pNodeHead->pNext = 0x8690CE00
  pNodeCur = 0x8690CE00, pNodeCur->data = 0x4, pNodeCur->pNext = 0x85E96AB8
  pNodeCur = 0x85E96AB8, pNodeCur->data = 0x3, pNodeCur->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x86529190
======================================== 
ShowList >> pNodeHead = 0x86529190 
  pNodeHead->data = 0x5, pNodeHead->pNext = 0x8690CE00
  pNodeCur = 0x8690CE00, pNodeCur->data = 0x4, pNodeCur->pNext = 0x85E96AB8
  pNodeCur = 0x85E96AB8, pNodeCur->data = 0x3, pNodeCur->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x86529190
ppNode is invalid
<< DriverEntry


完整实现:

/// @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

#define LISTNODE_CNT        6       ///< 单向链表节点数量
#define IS_LIST_LOOP        TRUE    ///< 单向链表是否回环

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, LISTNODE_CNT, IS_LIST_LOOP);
    ShowList(&pNode);

    /// 单向链表逆序
    ListReverse(&pNode);
    ShowList(&pNode);

    /// 释放链表
    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;
}


/// @file           Function.h
/// @brief          功能的实现

#ifndef __FUNCTION_H__
#define __FUNCTION_H__

#include <ntddk.h>
#include <WINDEF.H>

// for warning C4996: 'ExAllocatePool': was declared deprecated
#pragma warning(disable:4996)

typedef struct _node
{
    int data;
    struct _node * pNext;
} NODE,*PNODE;

/// 外部接口
/// @fn         ListReverse
/// @brief      单向链表翻转
BOOLEAN ListReverse(PNODE * ppNodeHead);

/// 内部接口

/// @fn         CreateList
/// @brief       建立一个单向链表
/// @param      PNODE * ppNode, 链表首节点指针, *ppNode 必须为空
/// @param      size_t nListSize, 链表的元素个数
/// @param      BOOLEAN bIsListLoop, 是否创建单回环链表, 如果是, 该链表首尾相接
void CreateList(PNODE * ppNode, size_t nListSize, BOOLEAN bIsListLoop);

void RemoveList(PNODE * ppNode);
void ShowList(PNODE * ppNode);

/// @fn         IsListLoop
/// @brief      链表是否回环
/// @param      IN PNODE * ppNodeHead, 单向链表头指针
/// @param      OUT size_t * pnElementsCnt, 单向链表的元素计数
/// @param      OUT PNODE * ppNodeTail, 单向链表尾指针
/// @return     BOOLEAN
/// @retval     TRUE, 链表回环
/// @retval     FALSE, 不是回环链表
/// @note OUT size_t & nElementsCnt 编译不过 ?
BOOLEAN IsListLoop(IN PNODE * ppNodeHead, OUT size_t * pnElementsCnt, OUT PNODE * ppNodeTail);

#endif


/// @file           Function.c
/// @brief 功能的实现

#include "Function.h"

void CreateList(PNODE * ppNode, size_t nListSize, BOOLEAN bIsListLoop)
{
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->pNext = NULL;
*ppNode = pNodeHead;

pNodeCur = pNodeHead;
for (nIndex = 1; nIndex < nListSize; nIndex++)
{
pNodeCur->pNext = (PNODE)ExAllocatePool(NonPagedPool, sizeof(NODE));

pNodeCur = pNodeCur->pNext;
pNodeCur->data = nIndex;
pNodeCur->pNext = NULL;
}

if (bIsListLoop)
pNodeCur->pNext = 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("========================================\r\n");
DbgPrint("ShowList >> pNodeHead = 0x%p\r\n", pNodeHead);
DbgPrint("\t pNodeHead->data = 0x%x, pNodeHead->pNext = 0x%p\n", pNodeHead->data, pNodeHead->pNext);

pNodeCur = pNodeHead->pNext;
while ((NULL != pNodeCur) && (pNodeCur != pNodeHead))
{
DbgPrint("\t pNodeCur = 0x%p, pNodeCur->data = 0x%x, pNodeCur->pNext = 0x%p\n",
pNodeCur, pNodeCur->data, pNodeCur->pNext);
pNodeCur = pNodeCur->pNext;
}
}

void RemoveList(PNODE * ppNode)
{
PNODE pNodeHead = NULL;
PNODE pNodeCur = NULL;
PNODE pNodeNext = NULL;

if ((NULL == ppNode) || (NULL == *ppNode))
{
return;
}

pNodeHead = *ppNode;

/// 释放头节点之外的数据
pNodeCur = pNodeHead->pNext;
while ((NULL != pNodeCur) && (pNodeCur != pNodeHead))
{
pNodeNext = pNodeCur->pNext;
ExFreePool(pNodeCur);
pNodeCur = pNodeNext;
}

/// 释放头节点
ExFreePool(pNodeHead);
*ppNode = NULL;
}

BOOLEAN IsListLoop(IN PNODE * ppNodeHead, OUT size_t * pnElementsCnt, OUT PNODE * ppNodeTail)
{
BOOLEAN bFind = FALSE;
PNODE pNodeCur = NULL;
PNODE pNodeHead = NULL;

NT_ASSERT(NULL != ppNodeHead);
NT_ASSERT(NULL != *ppNodeHead);
NT_ASSERT(NULL != pnElementsCnt);
NT_ASSERT(NULL != ppNodeTail);

pNodeHead = *ppNodeHead;
pNodeCur = pNodeHead->pNext;

*ppNodeTail = pNodeCur;
(*pnElementsCnt)++;

while (NULL != pNodeCur)
{
if (pNodeCur == pNodeHead)
{
bFind = TRUE;
break;
}

*ppNodeTail = pNodeCur;
pNodeCur = pNodeCur->pNext;
(*pnElementsCnt)++;
}

return bFind;
}

BOOLEAN ListReverse(PNODE * ppNodeHead) { BOOLEAN bListIsLoop = FALSE; size_t nElementsCnt = 0; PNODE pNodeCur = NULL; ///< 当前链表节点 PNODE pNodeNext = NULL; ///< 下一链表节点 PNODE pNodeTail = NULL; PNODE pListNewHead = NULL; PNODE pListNewTail = NULL; NT_ASSERT(NULL != ppNodeHead); NT_ASSERT(NULL != *ppNodeHead); /// 计算单向链表的元素个数N, 可以使此链表逆序算法适用于链表"回环"或"不回环"的情况 bListIsLoop = IsListLoop(ppNodeHead, &nElementsCnt, &pNodeTail); ///< 不关心链表是否回环, 只需要链表元素个数 if (nElementsCnt <= 1) return TRUE; ///< 链表节点2个以上, 才需要逆序 /// 遍历原始链表, 摘出每个元素, 作为新列表的头节点 /// 返回的头节点是最后一个元素 pNodeCur = *ppNodeHead; do { pNodeNext = pNodeCur->pNext; if (NULL == pListNewHead) { /// 新List的尾节点是原始List的头节点 pListNewTail = pNodeCur; pListNewTail->pNext = NULL; pListNewHead = pListNewTail; } else { pNodeCur->pNext = pListNewHead; pListNewHead = pNodeCur; } pNodeCur = pNodeNext; ShowList(&pListNewHead); } while (nElementsCnt-- > 1); if (bListIsLoop) pListNewTail->pNext = pListNewHead; ///< 处理回环情况 *ppNodeHead = pListNewHead; ShowList(&pListNewHead); return TRUE; }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: