线性表的链式表示
不要求逻辑上相邻的元素在物理存储上相邻,使用指针来表示元素之间的逻辑关系。
优点:
对线性表进行插入删除操作时不需要移动大量的元素,只需要修改对应元素的指针域即可,方便省时;
不需要为整个线性链表提前分配足够的存储空间;
当节点不再使用时,可以将存储空间进行及时的回收。
抽象链式类的定义
链式表使用指针来表示前后元素之间的关系,因此每个元素节点除了包含自身数据的相关信息外,还包括存储后续元素地址的指针。节点类的定义如下:
template <class type> class ListNode {//链表节点类定义 public: ListNode(); { next = nullptr;}//默认构造函数 ListNode(ListNode(const type &item, ListNode<type> *next1 = nullptr)) { data = item; next = next1; } //带参数的构造函数 type data; //节点数据域 ListNode<type> *next; //节点指针域 };
节点类的两个数据成员:data用于存储数据元素值,next用于指向下一个节点。两个构造函数用于给数据成员设置初值。其链表结构如下:
指示链表的第一个结点的指针称为头指针head,最后一个结点没有后继结点,指针域为空NULL或^,对于仅含有表头元素的链表为空表。
链表有三种类型,单链表、循环链表与双向链表三种。
抽象链表类的定义如下:
template <class type> class ablinklist :public ablist<type> { //继承线性表抽象类 public: ListNode<type> *GetHead() { //获得节点头指针 return head; } ListNode<type> *GetNext(ListNode<type> &n) { //获得节点n下一节点位置 return n.next == head ? n.next->next : n.next; //这句不是很明白 } type Get(int i); //获得第i元素 bool Set(type x, int i); //设置i处元素 ListNode<type> *Find(int i); //获得i处元素位置 ListNode<type> *Find1(type value); //获得元素value位置 void MakeEmpty(); virtual bool Insert(type value, int i) = 0; virtual bool Remove(int i) = 0; virtual bool Remove1(type value) =0; protected: ListNode<type> *head; };
抽象链表类各成员函数的实现
设置函数
//节点元素设置函数 template <class type> bool ablinklist<type>::Set(type x, int i) { ListNode<type> *p = Find(i); //找到节点 if (p == NULL || p == head) //链表不存在或空表 return false; else p->data = x; //设置元素 return true; }
取值函数
//获得第i元素值函数 template <class type> type ablinklist<type>::Get(int i) { LinkNode<type> *p = Find(i); //确定节点位置 assert(p && p != head); return p->data; //返回节点元素 }
清空链表函数
//清空链表函数 template<class type> void ablinklist<type>::MakeEmpty() { LinkNode<type> *q = head->next; //表头 int i = 0; while (i++ < length) { head->next = q->next; //删除第一个元素 delete q; //回收空间 q = head->next; //后移 } length = 0; }
搜索数据元素值为value的结点
//获得元素value位置 template<class type> ListNode<type> *ablinklist<type>::Find1(type value) { ListNode<type> *p = heda->next; //表头 int i = 1; while (i++ <= length && p->data != value) //i有效且为找到元素时 p = p->next; //后移 return p; }
定位函数
//获得i处元素位置 template<class type> ListNode<type> *ablinklist<type>::Find(int i) { ListNode<type> *p = head->next; //表头 if (i<0 || i>length) return NULL; //i无效,返回空 if (i == 0) return head; //空表 int j = 1; while (p != NULL && j < i) //遍历找元素 { p = p->next; j++; } return p; }
用C语言描述:
插入操作:在值为a的结点前面插入值为x的结点,若链表为空,则x为其头结点,若表中无a元素,在将x插入链表末尾。
//将元素x对应为链表格式 NODE *GetListNode(int x) { NODE *s; s=(NODE *)malloc(NODESIZE); if (s) { s->data=x; s->next=NULL; }//数据域x,指针域空 return(s); } NODE *InsertList(NODE *head,int a,int x) { NODE *s,*q; s=GetListNode(x); if (!s) return(head);//没有元素指针时 if (head==NULL){ //表为空时 head=s; return(head); } if (head->data==a){ //第一个结点满足 s->next=head; head=s; return(head); //不是很明白这一句---------------------- } q=head;//其它情况,进行查找 while (q->next!=NULL && q->next->data!=a) q=q->next; s->next=q->next; //插入 q->next=s; return(head); //返回头指针 }
删除操作:在头指针为head的链表中将值为a的结点删除
NODE *DeleteList(NODE *head,int a) { NODE *p,*q; if (head==NULL) return(NULL); if (head->data==a) //第一个结点满足 { p=head; head=head->next; free(p); return(head); } q=head; //其它情况,进行查找 while (q->next!=NULL && q->next->data!=a) q=q->next; if (q->next!=NULL);//找到,删除 { p=q->next; q->next=p->next; free(p);} return(head); //返回头指针 }