//链表的头插法
/***************************************/
//运用了OFFSET的宏定义
//通过GetNextPtr来实现OFFSET偏移
//最终实现链表结点的头插法。
//麻省算法导论
/***************************************/
#include<iostream>
#include<windows.h>
using namespace std;
#define OFFSET(x,m) (unsigned long)(&((x*)0)->m)
/****************结点*****************/
typedef struct _NODE_
{
int a;
int b;
_NODE_* pNext;
}Node,*pNode;
/*************************************/
/***************函数声明*************/
void InitNode(pNode* ppNodeTemp);
pNode* GerNextPtr(pNode pNodeTemp);
void LinkNode(pNode pNodeNew);
void FreeList();
pNode g_pHead = NULL;
unsigned long g_Offset = 0;
/************************************/
//主函数用于测试输入创建一个有三个结点的链表
int main()
{
pNode pNodeTemp = NULL;
for(int i =0;i<3;i++)
{
InitNode(&pNodeTemp); //创建
if(pNodeTemp!=NULL)
{
LinkNode(pNodeTemp); //连接
}
}
pNode pTravel = g_pHead;
while(pTravel != NULL)
{
cout<<pTravel->a<<endl;
pTravel = pTravel->pNext;
}
//程序结束时,释放内存
FreeList();
return 0;
}
//这里传参是传一个二维指针ppNode,然后解*后刚好是指针本身
//再进行动态内存申请。
//并赋值
void InitNode(pNode* ppNodeTemp)
{
*ppNodeTemp = new Node;
if(*ppNodeTemp != NULL)
{
(*ppNodeTemp)->a = 10;
(*ppNodeTemp)->b = 20;
(*ppNodeTemp)->pNext = NULL;
}
else
{
*ppNodeTemp = NULL;
}
}
//和OFFSET一起实现指针的后移,
//这里因为有a,b两个int型变量在Node结构体中,
//所以下移的字节数应该是8个
pNode* GetNextPtr(pNode pNodeTemp)
{
char* p =(char*)pNodeTemp;
return (pNode*)(p+OFFSET(Node,pNext));
}
//连接结点
void LinkNode(pNode pNodeNew)
{
//二维指针解*刚好是一维指针
//将其赋值为g_pHead相当于 pNodeNew->pNext = g_pHead
//因为通过GerNextPtr 下移了8个字节
*GetNextPtr(pNodeNew) = g_pHead;
//然后将头赋为pNodeNew
//实现了头部插入
g_pHead = pNodeNew;
}
//简单释放内存
void FreeList()
{
pNode pNodeDel = g_pHead;
while(pNodeDel != NULL)
{
g_pHead = g_pHead->pNext;
delete pNodeDel;
pNodeDel = g_pHead;
}
}