C++ 双向链表类

 说明:本文最早发布于 http://blog.csdn.net/Saimen 现转到本人网站,如果其它站转载,请标明出处为 http://www.5d232.com

本文介绍并实现了一个基于双向链表的C++类,命名为 CPtrArray, 用于保存动态生成的数据,相当于一个动态列表,可以管理动态分配的对象实例。

    用过VC的人可能都用过其中各种各样的Array类,在我也常用到,这让我编写程序方便了很多。
  
    最近这段时间在开发一个嵌入式的组态系统,使用DOS5.0,开发环境为Borlandc 3.1。为了在这样一个系统上实现我的组态功能,可是费了我不少心事设计,其中一项就是要解决画面的显示问题。组态系统要求用户自己设计画面,那么我们就来设计一个可以修改的监控画面,在VC开发后台时我使用Array类来保存监控画面的每一个对象,可是在BC31中呢,多少年都没有用过它了,我不知道它是不是也有Array类,有的话,这个类应该怎么用,与其再查找学习,不如自己动手编写一个,看样子,我是一个标准的CODE MAN,不管什么东东总想自己来写。
    不过还好,当年在学校的中数据结构还是没有白学。问题很快得到解决。

    我使用了一个双向链表解决这个问题,用它来实现结点的添加和删除实在太方便了。

    下面就是这个类的源代码部分,在此贴出,也希望和我一样,爱号、狂热于程序设计的朋友批抨指正。

首先贴上来的是我的一个数据类型定义,习惯了VC,就按VC的格式转换一下,当然,有经验的一看就知道是学UCOS的,呵呵,这点我承认,伟大的思想家鲁迅教育我们:要取其精华

/*
********************************************************
*
*        (c) Copyright 2003,Hu Wenjin
*             All Right Reserved
*
*
* File: datadef.h
* Auther: Hu Wenjin
* Data: 11.4.2003
*********************************************************
*/
/*
*********************************************************
* DATA TYPES DEFINE
*********************************************************
*/
#if !defined( _DATADEF_H )
#define _DATADEF_H

typedef signed long   INT;
typedef unsigned long       DWORD;
typedef INT                 BOOL;
typedef unsigned char  bool;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef float               FLOAT;
typedef unsigned long  UINT;
typedef unsigned long  DWORD;
typedef DWORD    COLORREF;
typedef char    CHAR;
typedef short    SHORT;
typedef long    LONG;
typedef unsigned char  INT8U;
typedef signed   char  INT8S;
typedef unsigned int  INT16U;
typedef signed   int  INT16S;
typedef unsigned long  INT32U;
typedef signed   long  INT32S;
typedef char*    LPCTSTR;
#define TRUE   1
#define FALSE  0
#define true   1
#define false  0

typedef struct
{
 LONG left;
 LONG top;
 LONG right;
 LONG bottom;
}RECT;


#endif

再接下来的,当然是  .h 文件了

#if !defined( _PTRARRAY_H )
#define _PTRARRAY_H
#include "datadef.h"
/*
*************************************************************************

  FILE:  PtrArray.h
  AUTHER: HuWenjin
  DATA:  9.27,2004

  Discrption:
 
 Modification:
 1.

*************************************************************************
*/

typedef struct
{
 void* m_pObj;   //结点中包含的数据指针
 void* m_pParent;  //上一个结点
 void* m_pChild;  //下一个结点
 int  m_nIndex;  //本结点在队列中的位置
 BOOL m_bDeleted;  //本结点是否被删除
}ST_OBJ;


class CJinPtrArray
{
public:
 CJinPtrArray( );
 virtual ~CJinPtrArray( );

public:
 void* SetAt(int nIndex,void* pObj); //修改指定点的对象指针为新指针
 int GetCount( ); //获取总数
 int Append( void* pObj );  //添加一个,从删除队列中添加,如果没有则再重新生成
 int DeleteAt( int nIndex );  //删除指定,没有释放内存,保留下次使用
 void* GetAt( int nIndex );  //获取指定的对象
 int RemoveAll( ); //清空全部结点数据,结点没有释放内存,保留下次使用

protected:
 ST_OBJ* m_pData; //对象指针
 int  m_nCount; //对象总数

protected:
 int MemFree( );  //从内存中删除所有的数据
 void* Sort( int nIndex = 0 ); //删除对象后排序,重设对列中的序号
};

#endif

最后就是CPP文件了

/**************************************************************************

  FILE: PtrArray.CPP
  AUTHER: HuWenjin
  DATA:  9.27,2004

  Discrption:


 Modification:
 1.

 

**************************************************************************/
#include "Includes.h"
#include "PtrArray.h"

///
// CJinPtrArray

CJinPtrArray::CJinPtrArray( )
{
 m_pData = NULL;
 m_nCount = 0 ;
}

CJinPtrArray::~CJinPtrArray()
{
 MemFree( );
}

int CJinPtrArray::MemFree( )
{
 ST_OBJ* pObj;
 ST_OBJ* pObjNext;

 pObj = m_pData;
 while( 1 )
 {
  if( !pObj )
   break;
  pObjNext = (ST_OBJ*)pObj->m_pChild;
  delete pObj;
  pObj = pObjNext;
 }
 
 return 0;
}

int CJinPtrArray::GetCount(  )
{
 return m_nCount;
}

int CJinPtrArray::RemoveAll( )
{
 ST_OBJ* pObj = m_pData;

 while( 1 )
 {
  if( !pObj )
   break; 
  pObj->m_bDeleted = TRUE;
  pObj->m_nIndex = -1;
  pObj = (ST_OBJ*)pObj->m_pChild;
 }
 m_nCount = 0 ;
 return 0;
}

int CJinPtrArray::Append( void* pObjAdd )
{
 ST_OBJ* pObj = m_pData;

 if( !pObjAdd )
  return -1;
 // 查找是否有空闲内存区,如果有则加入
 while( 1 )
 {
  if( !pObj )
   break;

  if( pObj->m_bDeleted == TRUE )
  {
   pObj->m_pObj = pObjAdd;
   pObj->m_bDeleted = FALSE;
   pObj->m_nIndex = m_nCount;
   m_nCount ++;
   return ( m_nCount-1 );
  }
  pObj = (ST_OBJ*)pObj->m_pChild;
 }

 // 没有空闲内存区,则再申请1个数据区加入
 pObj = NULL;
 pObj = new ST_OBJ;
 if( !pObj )
  return -1;
 
 pObj->m_bDeleted = FALSE;
 pObj->m_pObj = pObjAdd;
 pObj->m_nIndex = m_nCount;
 m_nCount ++;
 
 pObj->m_pParent = NULL;
 pObj->m_pChild = m_pData;
 if( m_pData )
  m_pData->m_pParent = pObj;

 // 保存当前的指针做为 ROOT 指针
 m_pData = pObj;

 return pObj->m_nIndex;
}

int CJinPtrArray::DeleteAt( int nIndex )
{
 ST_OBJ* pObj = m_pData;

 while( 1 )
 {
  if( !pObj )
   break;

  if( pObj->m_nIndex == nIndex )
  {
   pObj->m_bDeleted = TRUE;
   pObj->m_nIndex = -1;
   m_nCount --;
   //删除对象后应重新排序设定新序号
   Sort(nIndex);
   return m_nCount;
  }
  pObj = (ST_OBJ*)pObj->m_pChild;
 }
 return -1;
}


void* CJinPtrArray::GetAt( int nIndex )
{
 ST_OBJ* pObj = m_pData;

 while( 1 )
 {
  if( !pObj )
   break;
  if( pObj->m_nIndex == nIndex )
   return pObj->m_pObj;

  pObj = (ST_OBJ*)pObj->m_pChild;
 }
 return NULL;
}

void* CJinPtrArray::Sort( int nIndex )
{
 ST_OBJ* pObj = m_pData;

 while( 1 )
 {
  if( !pObj )
   break;

  if( pObj->m_nIndex < nIndex )
   goto NEXT_TIME;
  else if( pObj->m_nIndex > nIndex )
   pObj->m_nIndex -- ; 
NEXT_TIME:
  pObj = (ST_OBJ*)pObj->m_pChild;
 }
 return m_pData;
}

void* CJinPtrArray::SetAt(int nIndex, void *pTagObj)
{
 ST_OBJ* pObj = m_pData;
 void* pOldTagObj = NULL;
 
 while( 1 )
 {
  if( !pObj )
   break;
  if( pObj->m_nIndex == nIndex )
  {
   pOldTagObj = pObj->m_pObj;
   pObj->m_pObj = pTagObj;
   return pOldTagObj;
  }
 
  pObj = (ST_OBJ*)pObj->m_pChild;
 }
 return NULL;
}


    好了,大家可以看到整个程序并不是很长,应该还是很好理解的。
    在内存使用上,如果用户分配了20个空间,然后又删除的话,程序并没有马上释放内存,只是修改它的标识,因为用户可能马上又要用到多出的空间。
    所有的空间,在对象析构时释放。

©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页