zhangxiafll 2012-02-02
线性表包含 数据域和指针域 其中,data存储数据本身的值,next存储后继元素的地址 下面的图表示的是一个数据节点
单链表的结构示意图(包括空的单链表):
单链表的节点类:
template<classT> classNode { public: T data;//数据 Node<T> *next;//next指针 Node() { this->next=NULL;//构造空的节点 } Node(T data,Node<T> *next=NULL)//构造一个节点 { this->data=data; this->next=next; } };
单链表类声明如下:
#include<iostream> #include "Node.h"//单链表节点类 template<classT> classSinglyLinkedList //单链表类 { public: Node<T> *head;//单链表的头指针。 SinglyLinkedList();//构造空的单链表。 SinglyLinkedList(T value[], intn);//构造由指定的数组提供的单链表 ~SinglyLinkedList();//析构 boolisEmpty();//判断是否为空。 intlength();//获取长度 Node<T>* getNode(inti);//返回第i(i>=0)个节点指针 T get(inti);//返回第i个元素 boolset(inti,T x);//设置第i个元素为x template<classT> friend std::ostream& operator<<(std::ostream& out,SinglyLinkedList<T> &list); Node<T>* insert(inti,T x);//插入第I个节点并返回第i个节点的指针 boolremove(inti,T& old);//删除第i个元素,将删除的元素存放到old voidclear();//清空单链表 voidconcat(SinglyLinkedList<T> &list);//将List链接在当前单链表之后 };
单链表部分如构造空的链表对象,析构,判断为空的实现,没有要讲的算法,实现如下:
template<classT> SinglyLinkedList<T>::SinglyLinkedList()//构造空的单链表 { this->head=NULL; } template<classT> SinglyLinkedList<T>::~SinglyLinkedList()//析构 { clear(); } template<classT> boolSinglyLinkedList<T>::isEmpty()//判断链表是否为空 { returnthis->head==NULL; }
单链表的遍历操作,遍历单链表是指从第一个节点开始访问,沿着节点的Next可依次访问单链表中的各个节点,并且各个节点只被访问一次。实现的单链表遍历的基本算法如下:
intj=0; Node<T> *p=head; while(p!=NULL&&j<i) { j++; p=p->next; }
单链表的length(),get(),set(),clear()和输出等操作都基于以上算法。
template<classT> intSinglyLinkedList<T>::length() { inti=0; Node<T> *p=head;//创建一个用于遍的变量 while(p!=NULL) { i++; std::cout<<p->data; p=p->next; } returni; } template<classT> Node<T>* SinglyLinkedList<T>::getNode(inti) { if(i<0) returnNULL; intj=0; Node<T> *p=head; while(p!=NULL&&j<i) { j++; p=p->next; } returnp; } template<classT> T SinglyLinkedList<T>::get(inti) { Node<T> *p=getNode(i); if(p!=NULL) returnp->data; T d; returnd; //throw "单链表为空或者参数指定的元素不存在"; } template<classT> boolSinglyLinkedList<T>::set(inti,T x) { Node<T> *p=getNode(i); if(p!=NULL) { p->data=x; returntrue; } returnfalse; } template<classT> std::ostream& operator<<(std::ostream& out,SinglyLinkedList<T> &list) { Node<T> *p=list.head; out<<"("; while(p!=NULL) { out<<p->data; p=p->next; if(p!=NULL) out<<","; } out<<") "; returnout; } template<classT> voidSinglyLinkedList<T>::clear() { Node<T> *p=head; while(p!=NULL) { Node<T> *q=p; p=p->next; delete q; } head=NULL; }
单链表的插入操作,单链表不像顺序表,对与表的插入和删除很简单:
空表插入/头插入
Node<T> *q=NULL; if(head==NULL||i<0)//头插入(单链表为空或者) { q=newNode<T>(x,head); head=q; } 中间插入/尾插入 p->next=newNode<T>(x,p->next); 单链表insert()以及参数构造函数: template<classT> Node<T>* SinglyLinkedList<T>::insert(inti,T x) { Node<T> *q=NULL; if(head==NULL||i<0)//头插入(单链表为空或者) { q=newNode<T>(x,head); head=q; } else { intj=0; Node<T> *p=head; while(p->next!=NULL&&j<i-1) { j++; p=p->next; } q=newNode<T>(x,p->next); p->next=q; } returnq; } template<classT> SinglyLinkedList<T>::SinglyLinkedList(T table[],intn) { head=NULL; if(n>0) { head=newNode<T>(table[0]);//创建节点 Node<T> *rear=head;//创建一个指向头节点的指针 inti=1; while(i<n) { rear->next=newNode<T>(table[i++]); rear=rear->next; } } }
单链表的删除操作也分两类:
头删除
Node<T> *q=head; head=head->next; delete q;
中间/尾删除
Node<T> *q=p->next; if(q!=NULL)//判断删除节点 { p->next=q->next;//让删除节点的前驱Next指针下一节点 delete q;//删除该节点 }
单链表的删除函数remove()实现:
template<classT> boolSinglyLinkedList<T>::remove(inti,T &old) { if(i<0||head==NULL) { Node<T> *q=head; old=q->data; head=head->next; delete q; } else { Node<T> *p=getNode(i-1);//获取删除节点的前驱 if(p!=NULL&&p->next!=NULL)//判断删除节点和删除节点是否为空 { Node<T> *q=p->next;//新建一个节点指针,将删除接点复制过去 old=q->data; p->next=q->next;//让删除节点的前驱Next指针下一节点 delete q;//删除该节点 returntrue; } } returnfalse; } 单链表的链接函数:concat() template<classT> voidSinglyLinkedList<T>::concat(SinglyLinkedList<T> &list) { if(this->head==NULL) { this->head=list->head; } else { Node<T> *p=head; while(p->next!=NULL) { p=p->next; } p=list->head; } list->head=NULL;//设置单链表为空,否则运行出错 }
以上对C++单链表的分析 添加一个学生结构和一个测试函数:
Student.h structStudent { charnumber[10]; //学号 charname[20]; //姓名 doublescore; //得分 friend std::ostream& operator<<(std::ostream& out,Student &stu) { out<<"学号:"<<stu.number<<"姓名:"<<stu.name<<"得分:"<<stu.score; returnout; } }; 主函数: #include<iostream> #include "SinglyLinkedList.h" #include "Student.h" void_TestToSinglyLinkedList() { Student data[]={{"090313018","Silvester",45.4},{"090313018","捐赠",45.4},{"090313018","版主",45.6}}; SinglyLinkedList<Student> m(data,3); Student t; std::cout<<(m.isEmpty()?"不为空!":"该链表为空!")<<std::endl; std::cout<<"长度:"<<m.length()<<std::endl; std::cout<<"移除2个学生"<<m.remove(1,t)<<std::endl; std::cout<<"t:"<<t<<std::endl; std::cout<<"2个学生信息"<<m.getNode(1)<<std::endl; Student s={"415646","fdsfs",453.1}; std::cout<<m.get(1)<<m.set(1,s)<<m.insert(5,s)<<std::endl; } voidmain() { _TestToSinglyLinkedList(); system("pause"); }