这是一个系列的文章,主要目的是让初学者掌握链表的实现方法,并且从C过渡到C++。
作者:重庆工程职业技术学院 万青
在第2篇文章中,用C++实现了链表,但是链表节点的内容有局限性,从add、insert方法可以看出,参数只能是int,不能随意换成别的类型。
因此,本文中对链表类进行改良,add和insert方法用指针(指向包含数据的Object对象)作参数,更具有通用性,同时为后面的模板类埋下伏笔。
1 ////////////////////////////////////////////////////////////////////// 2 //改良版的链表类 3 //节点数据域改用指针 4 //add和insert方法用节点数据的指针作参数,更具有通用性,同时为后面的模板类打基础 5 //注意:链表本身不负责数据对象的清除,只负责节点对象的清除 6 ////////////////////////////////////////////////////////////////////// 7 8 #include<stdio.h> 9 class Object //存放数据的对象 10 { 11 public: 12 int data; 13 Object(int d) //构造函数 14 { 15 data=d; 16 } 17 }; 18 19 class CNode //节点类 20 { 21 public: 22 Object *obj; 23 CNode *next; 24 CNode(Object *p) //构造函数 25 { 26 obj=p; 27 } 28 }; 29 30 class CList //链表类 31 { 32 private: 33 CNode *head,*tail; //头、尾节点对象指针 34 int length; //节点总数 35 CNode *getPointerByIndex(int idx);//获取第idx个节点的对象指针(idx从1开始计) 36 public: 37 CList(); //构造函数(创建链表对象,并创建头节点,初始化头、尾指针等) 38 ~CList(); //析构函数(清除链表中的所有节点对象) 39 void add(Object *pObj); //添加节点到链表末尾 40 int insert(Object *pObj,int idx); //将节点插入到链表的idx位置之后 41 int del(int idx); //删除链表中的第idx个节点(idx从1开始计) 42 Object *get(int idx); //获取第idx个元素 43 int count(); //获取 44 void set(Object *pObj,int idx); //设置第idx个元素 45 Object **toArray(); //把链表转换为数组(指针数组) 46 }; 47 48 CList::CList() 49 { 50 CNode *pHead=new CNode(NULL); 51 head=tail=pHead; 52 tail->next=NULL; 53 length=0; 54 } 55 56 int CList::count(){return length;} 57 58 void CList::add(Object *pObj) 59 { 60 CNode *pNode=new CNode(pObj); 61 tail->next=pNode; 62 tail=pNode;//调整尾指针,指向新节点 63 tail->next=NULL; //设置结束标志 64 length++; //节点总数加1 65 } 66 67 CNode *CList::getPointerByIndex(int idx) 68 { 69 CNode *p; 70 int i=1; 71 if(idx<1 || idx>length) return NULL; 72 p=head; 73 74 while(i<=idx) 75 { 76 p=p->next; 77 i++; 78 } 79 return p; 80 } 81 82 int CList::insert(Object *pObj,int idx) 83 { 84 CNode *p; 85 p=getPointerByIndex(idx); 86 if(p!=NULL) 87 { 88 CNode *pNode=new CNode(pObj); 89 pNode->next=p->next; 90 p->next=pNode; 91 length++; 92 return 1; //成功,返回1 93 } 94 return 0;//失败,返回0 95 } 96 97 int CList::del(int idx) 98 { 99 CNode *p,*q; 100 if(idx<1 || idx>length) 101 return 0; //失败,返回0 102 103 //获得要删除节点的前一个节点指针 104 if(idx==1) p=head; 105 else p=getPointerByIndex(idx); 106 107 //删除p节点的后一节点 108 q=p->next; //记住后一节点的指针 109 p->next=q->next; 110 delete(q); 111 length--; 112 return 1;//成功,返回1 113 } 114 115 Object **CList::toArray() 116 { 117 Object **arr=new Object*[length]; 118 CNode *p; 119 p=head; 120 int n=0; 121 while(p->next!=NULL) 122 { 123 p=p->next; //head节点没有数据,先移动再读取 124 arr[n++]= p->obj; 125 } 126 return arr; 127 } 128 129 CList::~CList() 130 { 131 CNode *curr,*next; 132 curr=head; 133 while(curr->next!= NULL) 134 { 135 next=curr->next; 136 delete(curr); 137 curr=next; 138 } 139 delete(curr); 140 } 141 142 void show(CList *li) 143 { 144 //int i; 145 Object **arr=li->toArray(); 146 for(int i=0;i<li->count();i++) 147 printf("%d ",arr[i]->data); 148 printf("\n----------------\n"); 149 } 150 151 void main() 152 { 153 CList *li=new CList(); 154 li->add(new Object(100)); //等价于:Object *obj=new Object(100); li->add(obj); 155 li->add(new Object(101)); 156 li->add(new Object(102)); 157 li->add(new Object(103)); 158 show(li); 159 li->insert(new Object(200),2); 160 show(li); 161 li->insert(new Object(300),3); 162 show(li); 163 li->del(1); 164 show(li); 165 delete(li); 166 }