alg : 单向链表逆序 on drv
2013-05-29 18:19
309 查看
算法参考: http://blog.sina.com.cn/s/blog_4c1934d5010093ky.html
算法的思路:
遍历原始链表, 摘出每个元素, 作为新链表的头节点. 上一次摘出的原始链表元素作为本次摘出元素的Next节点.
当遍历完原始链表后, 新的链表就是逆序的单向链表.
我考虑了单向链表为回环的情况, 在驱动层实现了一次.
实验过了, 回环和非回环单向链表逆序都正常.
单链表逆向的实现:
运行结果
完整实现:
算法的思路:
遍历原始链表, 摘出每个元素, 作为新链表的头节点. 上一次摘出的原始链表元素作为本次摘出元素的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; }
相关文章推荐
- alg : 单向链表回环的判断 on drv
- alg : 单向链表排序 on drv
- 单向链表的逆序,不使用额外节点存储实现
- 单向链表逆序
- 单向链表逆序
- 单向链表的基本操作及逆序实现
- 算法题18 逆序(字符串、整数、单向链表)
- Reverse Linked List II 单向链表逆序(部分逆序)
- 【数据结构练习】单向链表实现、链表逆序实现
- 单向链表逆序
- 单向链表逆序
- C语言解字符串逆序和单向链表逆序问题的代码示例
- 将一个单向链表逆序
- 单向链表逆序
- 线性单向链表的逆序排列算法一例
- C/c++语言,求单向链表的逆序_普通方法_header+p+q工作指针
- 数据结构:单向链表的逆序
- 已知单向链表的头结点head,写一个函数把这个链表逆序 ( Intel)
- java版的单向链表的逆序输出
- 《C算法》读书笔记(5):单向链表逆序