免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: jeanlove
打印 上一主题 下一主题

[C++] 自己实现的一个list类,可以增删反转,请大家拍砖 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-01-23 16:07 |显示全部楼层 |倒序浏览
10可用积分
考虑了几个因素: 内存管理,错误处理,记录head的位置等等。在win和solaris上面用gcc均测试通过。

想请各位看官点评一下,看看有没有设计上的缺陷(内存? 排错?)或者性能上的风险。这个类以后会作为一个生产程序的基础,所以我需要很仔细地来考量它。

10分待送,给指出本程序弱点的dx

cat>main.cpp
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;
#define STRMAX 20
class node{
       node(){
              data=new char[STRMAX+1];
              strncpy(data,"head",5);
              pnext=NULL;
       }
       node(const char* content){
              data=new char[STRMAX+1];
              strncpy(data,content,STRMAX);
              pnext=NULL;
       }
       ~node(){
               if(data)delete data;
               pnext=NULL;
       }
public:
       char* data;
       node* pnext;
       //这样做是为了保证node都是在堆上生成的。因为如果在stack上有node, 而主程序去delete这个node
       //的地址,程序就会崩溃。所以内存管理就包装在node类的内部,外部用函数去掉用它                          
       static node* createNode(){
              printf("createNode() called\n");
              return new node();
       }
       static node* createNode(const char* content){
              if(content==NULL){
                 printf("createNode() received null string for input param\n");
                 return new node();
              }
              if(strlen(content)>=STRMAX){
                 printf("createNode() input string is longer than %d, will be truncated\n",STRMAX);
              }
              printf("createNode(%s) called\n",content);
              return new node(content);
       }
       static void destroyNode(node* pn){
              delete pn;
       }
       void printNode(){
             printf("node data=%s\n",data);
       }
};

class list{
       node* head;
       node* tail;
public:
       list(){
         head=node::createNode();
         tail=head;
         printf("list::ctor() finish\n");
       }
       ~list(){
         node* cur=head;
         node* next;
         do{
               next=cur->pnext;
               node::destroyNode(cur);
               cur=next;
         }while(cur);
       }
       void print(){
            node* cur=head;
            do{
                 printf("node pointer=%d,next=%d\n",cur,cur->pnext);
                 cur->printNode();
                 cur=cur->pnext;
            }while(cur);
       }
       void printTail(){
            printf("list tail information:");
            tail->printNode();
       }
       bool append(node* pn){
         if(pn==NULL){
            printf("append() fail with null input pointer param\n");
            return false;
         }
         printf("list::append() called\n");
         tail->pnext=pn;
         tail=pn;
         return true;
       }
       bool insert(int insertAfter/*在位置insertAfter之后插入一个节点 从0开始算*/,node* pn){
            //e.g, if list has mutiple elements and insertAfter is 0
            //then insert it after the head node
            if(insertAfter<0){
              printf("insert() received negative param:%d\n",insertAfter);
              return false;
            }
            if(pn==NULL){
              printf("insert fail with null input pointer param\n");
              return false;
            }
            node* next=head;
            while(insertAfter){
                  next=next->pnext;
                  if(next==NULL){
                     printf("traverse next pointer %d insertAfter is NULL, insert() failed!!!!!!!\n");
                     return false;
                  }
                  --insertAfter;
            }
            if(next==tail)
                 append(pn);
            else{
                 printf("list::insert() called\n");
                 pn->pnext=next->pnext;
                 next->pnext=pn;
            }
            return true;
       }
       bool remove(int at){//删除链表某个位置上的元素
            //Never remove head node
            if(at<=0){
              printf("insert() received <=0 param:%d\n",at);
              return false;
            }
            node* next=head;
            node* old;
            while(at){
                  old=next;
                  next=next->pnext;
                  if(next==NULL){
                     printf("next %d insertAfter is NULL, insert() failed\n");
                     return false;
                  }
                  --at;
            }
            //printf("old->data is %s,pnext->data is%s\n",old->data,old->pnext->data);
            //printf("next->pnext data is %s\n",next->pnext->data);
            old->pnext=next->pnext;
            //printf("now,old->data is %s,pnext->data is%s\n",old->data,old->pnext->data);
            if(tail==next){
               printf("remove tail, reset tail\n");
               tail=old;
            }
            node::destroyNode(next);
            return true;
       }
       void reverse(){
            printf("====================开始反转======================\n");
            if(head==tail)return;
            node* cur=head->pnext;
            node* rev=cur->pnext;
            node* next;
            cur->pnext=NULL;
            while(rev){
                next=rev->pnext;
                rev->pnext=cur;
                cur=rev;
                rev=next;
            }
            head->pnext=cur;
       }
};

int main(int argc, char *argv[])
{
    list l;
    l.append(node::createNode("1st node"));
    l.append(node::createNode("2nd node"));
    l.append(node::createNode("4th node"));
    l.insert(2,node::createNode("3rd node"));
    l.insert(4,node::createNode("5th node"));
    l.insert(5,node::createNode("6 okorfail???"));
    l.print();
    printf("========================================================\n");
    l.remove(3);
    l.remove(5);
    l.print();
    l.reverse();
    l.print();
    return EXIT_SUCCESS;
}

[ 本帖最后由 jeanlove 于 2009-1-23 16:08 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-01-23 16:40 |显示全部楼层
原帖由 hellioncu 于 2009-1-23 16:20 发表
strncpy(data,content,STRMAX);
content的长度=STRMAX时,data中不会最后添加\0
为空时remove会异常吧
如果要在指定位置插入删除,你的实现中需要遍历,可以考虑增加一个指针数组作为索引


谢谢,content长度=STRMAX的情况确实没有考虑到
不过list不会为空,因为list的ctor里面提供了至少一个head,而且head是私有变量,外界无法delete它的。

增加指针数组确实是个好办法。我没有仔细研究过stl里面list的实现是不是有指针数组,但是我以前的经验告诉我stl的list实现虽然很强大但是效率并不高,好多函数掉用和内存操作。从性能的考虑其实stl并不是到处适用的。以前看过一个帖子,用stl类来实现无递归的hanoi塔方案,结果发现还没有自己处理堆栈的效率高,就是要多写些代码。

论坛徽章:
0
3 [报告]
发表于 2009-01-23 16:42 |显示全部楼层
原帖由 太平绅士 于 2009-1-23 16:38 发表
list无法包含其它类型的node,
因为list不是template,node也没用virtual ~node()

嗯,dtor没有用virtual关键字,确实存在风险... ...

论坛徽章:
0
4 [报告]
发表于 2009-01-23 16:56 |显示全部楼层
原帖由 太平绅士 于 2009-1-23 16:47 发表
remove / insert 将一个链表随机访问,链表很长的话,有效率上的风险。

---------------------------

sorry,我吹毛求疵了。其实你的程序写的不错的。
不过既然 “作为一个生产程序的基础”,还是严格点好。

谢谢,这个效率风险是个很好的建议。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP