写了个链表类,大家批批,看看有什么值得改进的地方。
#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;
};
问题点数:20、回复次数:10Top
1 楼kikikind(可乐)回复于 2006-03-04 15:41:15 得分 5
1.代码风格很好
2.继续多做练习
3.私人帮你顶一下!:)Top
2 楼zzw820626(偶要分,偶要星星)回复于 2006-03-06 17:11:18 得分 0
和sgi 的stl比比不就知道了Top
3 楼bluejugar(2046,那年我64.)回复于 2006-03-19 02:17:23 得分 5
小可不才,愿提一些建议:
1.加上预编译头#ifdef ... #define .. #endif
2.CHebcaListItem(T value)
{
Init();
data = value;
};
一般来说,作为模板参数而言,因为不知道传入参数类型,用
CHebaclListItem(const T& value)可能要好一点.
3.类名不可理解,这会造成使用困难.简捷、规范的命名是所有C++库的安身立命之道。
4.三个类之间的关系太紧密。难以扩展和重用。适当的增加中间层,可能比较好一点。比如说对Iterator的重用等。
5。从楼主的代码可以看得出楼主是比较了解JAVA的,但JAVA里面的库有一个重要缺陷,就是各个库之间的接口不统一,相比之下,STL在这方面要稍加规范。
楼主的代码没有细看。总的来说还是写得不错的。继续加油干吧。Top
4 楼SeekTruth(鹤舞白沙)回复于 2006-03-20 16:50:37 得分 5
感觉iterator与container的耦合性太强Top
5 楼qkhhgutg(太子)回复于 2006-03-24 13:25:46 得分 0
接分Top
6 楼moonhappy(飞水)回复于 2006-03-25 08:00:32 得分 0
very goodTop
7 楼leechiyang(逮老鼠的狗算不算好猫?)回复于 2006-03-25 11:22:03 得分 0
to:bluejugar
谢谢您的建议.
1.以后不用 #pragma once 我也感觉#ifdef ... #define .. #endif更好些
2.CHebaclListItem(const T& value)确实好些,至少省掉了一次对象构造.
3.Hebca是公司缩写,不想和他人的代码产生冲突,所以就成这样了...
其他的常用避免命名冲突的方法都有什么?
4.确实是个问题.没有考虑过.
5.对java只是略微知道点,没写过一个程序:), 类里面的函数和使用方法大多是从stl里来的。但是对stl也不是很了解。
没看过什么设计模式的资料,只是凭空想象。所以请大家指正。Top
8 楼bitflying()回复于 2006-04-07 14:50:16 得分 5
1. 名字冲突可以用namespace解决。
2。各个类中的init()方法似无必要,可以用构造函数的初始化列表代替,比如:
CHebcaList(CHebcaList<T> &value):m_pHead(0),m_pEnd(0),m_nSize(0)
3. 楼主能否解释一下,各个类中,数据成员都用protected修饰的意图是什么?这几个类似乎都是具体的实现类,不打算做基类。
4. 函数体定义全部都内联到类定义中,又不加inline关键字,这种风格的确是JAVA的。但如果用在C++中问题很多,最突出的问题是,如果头文件被included 到多个源文件中,在链接的时候会有名字冲突。
Top
9 楼leechiyang(逮老鼠的狗算不算好猫?)回复于 2006-04-27 08:50:51 得分 0
我也想把函数定义放到头文件中,实现部分放到CPP文件中,但是这种模板类编译通不过.如果可以这么做,还请给个例子.真的不知道怎么做,试了很长时间都不行.Top
10 楼sambian()回复于 2006-04-29 11:02:02 得分 0
这种方法不行.模板还没被实例化,不能放入CPP文件中.Top




