写了个链表类,大家批批,看看有什么值得改进的地方。

leechiyang 2006-03-04 10:17:27
#pragma once

template<class T>
class CHebcaListIterator;

template<class T>
class CHebcaListItem
{
public:
CHebcaListItem()
{
Init();
};
CHebcaListItem(T value)
{
Init();
data = value;
};
void Init()
{
next = 0;
previous = 0;
}
T data;
CHebcaListItem * previous;
CHebcaListItem * next;
};


template<class T>
class CHebcaList
{
public:
CHebcaList(void)
{
Init();
};


CHebcaList(CHebcaList<T> &value)
{
Init();
RemoveAll();
CHebcaListIterator<T> iter = value.GetIterator();
while(itor.Next())
{
PushBack(*itor.Current());
}
};

~CHebcaList(void)
{
RemoveAll();
};

void Init()
{
m_pHead = 0;
m_pEnd = 0;
m_nSize = 0;
};

//取得迭代器,指向第一个元素前面.
CHebcaListIterator<T> GetIterator()
{
return CHebcaListIterator<T>(&m_pHead, &m_pEnd);
};

//取得迭代器,指向最后一个元素后面.
CHebcaListIterator<T> GetIteratorBack()
{
return CHebcaListIterator<T>(&m_pHead, &m_pEnd);
};

//在链表中position前面插入元素,position不能位于最后一个元素后面,
//如果需要在最后插入元素,用PushBack()
CHebcaListIterator<T> Insert(CHebcaListIterator<T> position, T value)
{
CHebcaListItem * pElement = new CHebcaListItem<T>(value);
CHebcaListIterator<T> iter = GetIterator();

if(position.m_pCurrent == 0)
{
if(m_pHead)
{
pElement->next = m_pHead;
m_pHead->previous = pElement;
m_pHead = pElement;
}
else
{
m_pHead = pElement;
m_pEnd = pElement;
}
}
else
{
if(position.m_pCurrent->previous)
{
pElement->next = position.m_pCurrent->previous->next;
pElement->previous = position.m_pCurrent->next->previous;
position.m_pCurrent->previous->next = pElement;
position.m_pCurrent->next->previous = pElement;
}
else
{
pElement->next = m_pHead;
m_pHead->previous = pElement;
m_pHead = pElement;
}
}

m_nSize ++;
iter.SetCurrent(pElement);
return iter;
};

//弹出最后一个元素
CHebcaListIterator<T> PopBack()
{
CHebcaListIterator<T> iter = GetIterator();
while(iter.HasNext())
{
iter.Next();
}
return Remove(iter);
};

//弹出第一个元素
CHebcaListIterator<T> PopFront()
{
CHebcaListIterator<T> iter = GetIterator();
iter.Next();
return Remove(iter);
};

//在最后插入一个元素
CHebcaListIterator<T> PushBack(T value)
{
CHebcaListIterator<T> iter = GetIterator();
CHebcaListItem<T> * pElement = new CHebcaListItem<T>(value);

if(m_pHead == 0)
{
m_pHead = pElement;
m_pEnd = pElement;
}
else
{
pElement->previous = m_pEnd;
m_pEnd->next = pElement;
m_pEnd = pElement;
}
m_nSize ++;
iter.SetCurrent(m_pEnd);
return iter;
};

//在前面插入一个元素
CHebcaListIterator<T> PushFront(T value)
{
CHebcaListIterator<T> iter = GetIterator();
iter.Next();
return Insert(iter, value);
};

//删除position指向的一个元素
CHebcaListIterator<T> Remove(CHebcaListIterator<T> position)
{
if(position.m_pCurrent)
{
CHebcaListItem<T> * previous = position.m_pCurrent->previous;
CHebcaListItem<T> * next = position.m_pCurrent->next;
if(previous && next)
{
previous->next = next;
next->previous = previous;
}
if(previous && !next)
{
previous->next = 0;
m_pEnd = previous;
}
if(!previous && next)
{
m_pHead = next;
next->previous = 0;
}
if(!previous && !next)
{
m_pHead = 0;
m_pEnd = 0;
}
delete position.m_pCurrent;
m_nSize --;
}
return GetIterator();
};

//删除所有的元素
void RemoveAll()
{
CHebcaListIterator<T> iter = GetIterator();
while(iter.HasNext())
{
PopFront();
iter = GetIterator();
}
};

//取得链表长度
int GetSize()
{
return m_nSize;
};

//链表是否为空
int IsEmpty()
{
return m_pHead == 0;
};

//赋值运算符重载
CHebcaList & operator =(CHebcaList<T> &value)
{
RemoveAll();
CHebcaListIterator<T> iter = value.GetIterator();
while(itor.Next())
{
PushBack(*itor.Current());
}
return *this;
};

//==运算符重载
int operator==(CHebcaList<T> & value)
{
if(GetSize() == value.GetSize())
{
CHebcaListIterator<T> itor1 = value.GetIterator();
CHebcaListIterator<T> itor2 = GetIterator();
while(itor1.Next())
{
if(*itor1.Current() != *itor2.Next())
{
return 0;
}
}
return 1;
}
else
{
return 0;
}
};

protected:
CHebcaListItem<T> * m_pHead;
CHebcaListItem<T> * m_pEnd;
int m_nSize;
};


//链表迭代器
//首元素前面等价于尾元素后面
//while(iter.Next()){...}遍历一遍后可以继续使用while(iter.Next()){...}进行遍历

template<class T>
class CHebcaListIterator
{
public:
CHebcaListIterator()
{
Init();
};

CHebcaListIterator(CHebcaListItem<T> ** header, CHebcaListItem<T> ** ender)
{
Init();
m_ppHeader = header;
m_ppEnder = ender;
};

//后面是否还有元素
int HasNext()
{
if(m_pCurrent)
{
return m_pCurrent->next != 0;
}
else
{
return *m_ppHeader != 0;
}
};

//向后移动一个元素,如果到了末尾元素后面返回0,否则返回指向当前元素的指针
T * Next()
{
if(m_pCurrent == 0)
{
m_pCurrent = *m_ppHeader;
}
else
{
m_pCurrent = m_pCurrent->next;
}

if(m_pCurrent)
{
return & m_pCurrent->data;
}
else
{
return 0;
}
};


//向前移动一个元素,如果到了首元素前面返回0,否则返回指向当前元素的指针
T * Previous()
{
if (m_pCurrent == 0)
{
if(m_ppEnder)
{
m_pCurrent = *m_ppEnder;
if(m_pCurrent)
{
return & m_pCurrent->data;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
else
{
m_pCurrent = m_pCurrent->previous;
if(m_pCurrent)
{
return & m_pCurrent->data;
}
else
{
return 0;
}
}
};

//返回指向当前元素的指针,如果当前位置为首元素前或尾元素后面,返回0
T * Current()
{
if(m_pCurrent)
{
return & m_pCurrent->data;
}
else
{
return 0;
}
};

//重置当前位置,指向首元素前或者末元素后面
void Reset()
{
m_pCurrent = 0;
};

//指定当前位置(一般不使用)
CHebcaListItem<T> * SetCurrent(CHebcaListItem<T> * current)
{
if(current)
{
m_pCurrent = *m_ppHeader;
while(m_pCurrent != current)
{
m_pCurrent = m_pCurrent->next;
}
}
else
{
m_pCurrent = current;
}
return m_pCurrent;
};
protected:
void Init()
{
m_ppHeader = 0;
m_ppEnder = 0;
m_pCurrent = 0;
};
CHebcaListItem<T> ** m_ppHeader;
CHebcaListItem<T> ** m_ppEnder;
public:
CHebcaListItem<T> * m_pCurrent;
};
...全文
450 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
sambian 2006-04-29
  • 打赏
  • 举报
回复
这种方法不行.模板还没被实例化,不能放入CPP文件中.
leechiyang 2006-04-27
  • 打赏
  • 举报
回复
我也想把函数定义放到头文件中,实现部分放到CPP文件中,但是这种模板类编译通不过.如果可以这么做,还请给个例子.真的不知道怎么做,试了很长时间都不行.
bitflying 2006-04-07
  • 打赏
  • 举报
回复
1. 名字冲突可以用namespace解决。
2。各个类中的init()方法似无必要,可以用构造函数的初始化列表代替,比如:
CHebcaList(CHebcaList<T> &value):m_pHead(0),m_pEnd(0),m_nSize(0)
3. 楼主能否解释一下,各个类中,数据成员都用protected修饰的意图是什么?这几个类似乎都是具体的实现类,不打算做基类。
4. 函数体定义全部都内联到类定义中,又不加inline关键字,这种风格的确是JAVA的。但如果用在C++中问题很多,最突出的问题是,如果头文件被included 到多个源文件中,在链接的时候会有名字冲突。

leechiyang 2006-03-25
  • 打赏
  • 举报
回复
to:bluejugar
谢谢您的建议.
1.以后不用 #pragma once 我也感觉#ifdef ... #define .. #endif更好些
2.CHebaclListItem(const T& value)确实好些,至少省掉了一次对象构造.
3.Hebca是公司缩写,不想和他人的代码产生冲突,所以就成这样了...
其他的常用避免命名冲突的方法都有什么?
4.确实是个问题.没有考虑过.
5.对java只是略微知道点,没写过一个程序:), 类里面的函数和使用方法大多是从stl里来的。但是对stl也不是很了解。

没看过什么设计模式的资料,只是凭空想象。所以请大家指正。
moonhappy 2006-03-25
  • 打赏
  • 举报
回复
very good
净天宇 2006-03-24
  • 打赏
  • 举报
回复
接分
SeekTruth 2006-03-20
  • 打赏
  • 举报
回复
感觉iterator与container的耦合性太强
bluejugar 2006-03-19
  • 打赏
  • 举报
回复
小可不才,愿提一些建议:
1.加上预编译头#ifdef ... #define .. #endif
2.CHebcaListItem(T value)
{
Init();
data = value;
};
一般来说,作为模板参数而言,因为不知道传入参数类型,用
CHebaclListItem(const T& value)可能要好一点.
3.类名不可理解,这会造成使用困难.简捷、规范的命名是所有C++库的安身立命之道。
4.三个类之间的关系太紧密。难以扩展和重用。适当的增加中间层,可能比较好一点。比如说对Iterator的重用等。
5。从楼主的代码可以看得出楼主是比较了解JAVA的,但JAVA里面的库有一个重要缺陷,就是各个库之间的接口不统一,相比之下,STL在这方面要稍加规范。

楼主的代码没有细看。总的来说还是写得不错的。继续加油干吧。
zzw820626 2006-03-06
  • 打赏
  • 举报
回复
和sgi 的stl比比不就知道了
kikikind 2006-03-04
  • 打赏
  • 举报
回复
1.代码风格很好
2.继续多做练习
3.私人帮你顶一下!:)

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧