以链表为载体学习C++(4)

这是一个系列的文章,主要目的是让初学者掌握链表的实现方法,并且从C过渡到C++。

作者:重庆工程职业技术学院 万青

第3篇文章中,add、insert方法的参数变成了指针,假设所有类的基类是Object,那么该指针是可以指向任何对象的。也就是说,链表节点可以容纳任意类型的数据(当然只是存了一个首地址)。

不过更彻底的解决办法是用模板类:

  1 #include<iostream>
  2 using namespace std;
  3 template<class T> 
  4 class CNode //节点类
  5 {
  6     public:
  7         T data;
  8         CNode *next;
  9         CNode(T d) //构造函数
 10         {
 11             data=d;
 12             next=NULL;
 13         }
 14 };
 15 template<class T> 
 16 class CList //链表类
 17 {
 18     private:
 19         CNode<T> *head,*tail; //头、尾节点对象指针
 20         int length; //节点总数
 21     public:
 22         CList(); //构造函数(创建链表对象,并创建头节点,初始化头、尾指针等)
 23         void add(T data); //添加值为data的节点到链表末尾
 24         int insert(T data,int idx); //将数据data插入到链表的idx位置之后
 25         int del(int idx); //删除链表中的第idx个节点(idx从1开始计)
 26         CNode<T> * getPointerByIndex(int idx);//获取第idx个节点的对象指针(idx从1开始计)
 27         T* toArray(); //显示(遍历)链表的所有节点
 28         int getLength()
 29         {
 30             return length;
 31         }
 32         ~CList(); //析构函数(清除链表中的所有节点对象)
 33 };
 34 
 35 template<class T> 
 36 CList<T>::CList()
 37 {
 38     head=tail=new CNode<T>(0);
 39     length=0;
 40 }
 41 
 42 template<class T> 
 43 void CList<T>::add(T data)
 44 {
 45     CNode<T> *pNode=new CNode<T>(data);
 46     tail->next=pNode; 
 47     tail=pNode;//调整尾指针,指向新节点
 48     length++; //节点总数加1
 49 }
 50 
 51 template<class T> 
 52 CNode<T> * CList<T>::getPointerByIndex(int idx)
 53 {
 54     CNode<T> *p;
 55     int i=1;
 56     if(idx<1 || idx>length) return NULL;
 57     p=head;
 58 
 59     while(i<=idx)
 60         {
 61             p=p->next;
 62             i++;
 63         }
 64     return p;
 65 }
 66 
 67 template<class T> int CList<T>::insert(T data,int idx)
 68 {
 69     CNode<T> *p;
 70     p=getPointerByIndex(idx);
 71     if(p!=NULL)
 72     {
 73         CNode<T> *pNode=new CNode<T>(data);
 74         pNode->next=p->next;
 75         p->next=pNode;
 76         length++;
 77         return 1; //成功,返回1
 78     }
 79     return 0;
 80 }
 81 
 82 template<class T> int CList<T>::del(int idx)
 83 {
 84     CNode<T> *p,*q;
 85     if(idx<1 || idx>length)
 86         return 0; //失败,返回0
 87 
 88     //获得要删除节点的前一个节点指针
 89     if(idx==1) p=head;
 90     else p=getPointerByIndex(idx);
 91 
 92     //删除p节点的后一节点
 93     q=p->next; //记住后一节点的指针
 94     p->next=q->next;
 95     //delete(q->data);
 96     delete(q);
 97     length--;
 98     return 1;//成功,返回1
 99 }
100 
101 template<class T> T* CList<T>::toArray()
102 {
103     T *a=new T[length];
104     CNode<T> *p;
105     p=head;
106     for(int i=0;i<length;i++)
107     {
108         p=p->next; //head节点没有数据,先移动再读取
109         a[i]=p->data;
110     }
111     return a;
112 }
113 
114 
115 template<class T> CList<T>::~CList()
116 {
117     CNode<T> *curr,*tmp;
118     curr=head;
119     for(int i=0;i<=length;i++)
120     {
121         tmp=curr;
122         curr=curr->next;
123         //delete(tmp->data);
124         delete(tmp);
125     }
126 }
127 
128 void showList(CList<int> *li)
129 {
130     int *a=li->toArray();
131     for(int i=0;i<li->getLength();i++)
132         cout<<a[i]<<" ";
133     cout<<"\n-------------------\n";
134 }
135 
136 void main()
137 {
138     CList<int> *li;
139     li=new CList<int>();
140     //int a=100,b=101,c=102;
141     //li->add(&a);
142     //li->add(&b);
143     //li->add(&c);
144     li->add(100);
145     li->add(101);
146     li->add(102);
147     li->add(103);
148     showList(li);
149     li->insert(200,2);
150     showList(li);
151     li->insert(300,3);
152     showList(li);
153     li->del(1);
154     showList(li);
155     delete(li);
156 }

模板类不仅可以用于节点数据是对象指针的场合,也适用于节点数据是基本类型(如int)的场合。在此基础上,看到Java中的LinkedList<T>和C#中的List<T>,就不会有唐突的感觉了。稍微不同的是,Java和C#中去掉了“*”,把“->”变成“.”,对象指针也换了个名字叫“对象句柄”。

posted @ 2012-12-22 18:10  Programmer168  阅读(164)  评论(0)    收藏  举报