【二】数据结构之List
来源:互联网 发布:郫都区人民政府 知乎 编辑:程序博客网 时间:2024/06/05 18:43
【二】数据结构之List
数据结构中,线性表无独有偶,除了Vector还有另外一种ADT,就是我们要讨论的List,与向量Vector有所不同,列表List不在是系统连续的内存空间,也就是说不是基于数组来实现的了,尽管在物理上不是线性的,但是抽象层次上,List在逻辑上依旧是现行表,因此List优化了Vector插入,删除操作的劣势,但是在查找方面却不如Vector的二分查找来的快。
List有哪些接口呢?
恩,接下来,给出具体的实现,注释都很详细,很容易理解。
节点的实现如下:
#ifndef LISTNODE_H#define LISTNODE_Htypedef int Rank;//秩#define ListNodePosi(T) ListNode<T>* //列表节点位置template <typename T> struct ListNode{//列表节点模板类(以双向链表形式实现) //成员 T data; ListNodePosi(T) pred; ListNodePosi(T) succ; //构造函数 ListNode(){}//针对header 和trailer的构造 ListNode(T e, ListNodePosi(T) p = NULL, ListNodePosi(T) s = NULL) : data(e), pred(p), succ(s){}//默认构造器 //操作接口 ListNodePosi(T) insertAsPred(T const& e);//紧靠当前节点之前插入新节点 ListNodePosi(T) insertAsSucc(T const& e);//紧靠当前节点之后插入新节点};//类函数定义template <typename T>//将e紧靠当前节点之前插入于当前节点所属列表(设有哨兵头节点header)ListNodePosi(T) ListNode<T>::insertAsPred(T const& e){ ListNodePosi(T) x = new ListNode(e, pred, this);//创建新节点 pred->succ = x; pred = x;//设置正向链接 return x;//返回新节点的位置}template <typename T>//将e紧靠当前节点之后插入于当前节点所属列表(设有哨兵头节点trailer)ListNodePosi(T) ListNode<T>::insertAsSucc(T const& e){ ListNodePosi(T) x = new ListNode(e, this, succ);//创建新节点 succ->pred = x; succ = x;//设置反向链接 return x;//返回新节点的位置}#endif // !LISTNODE_H
列表的实现如下:
#ifndef LIST_H#define LIST_H#include "listNode.h"template<typename T> class List{//列表模板类 private: int _size; ListNodePosi(T) header; ListNodePosi(T) trailer;//规模、头尾哨兵protected: void init();//初始化 int clear();//清楚所有节点至表空 void copyNodes(ListNodePosi(T), int);//复制列表中自p起的n项 void merge(ListNodePosi(T)&, int, List<T>&, ListNodePosi(T), int);//归并 void mergeSort(ListNodePosi(T)&, int);//归并排序 void selectionSort(ListNodePosi(T), int);//选择排序 void insertionSort(ListNodePosi(T), int);//插入排序public: //构造函数 List(){ init(); } List(List<T> const& L); List(List<T> const& L, Rank r, int n);//复制列表L中自第r项起的n项 List(ListNodePosi(T) p, int n);//复制列表中自P位置起的n个节点 //析构函数 ~List();//释放所有节点 //只读访问接口 Rank size()const{ return _size; };//规模 bool empty()const { return _size <= 0 };//判空 ListNodePosi(T) operator[] (Rank r)const;//重载 支持循秩访问 ListNodePosi(T) first()const{ return header->succ; }//首节点位置 ListNodePosi(T) last()const{ return trailer->pred; }//末节点位置 bool valid(ListNodePosi(T) p){//判断p位置对外是否合法 return p && (trailer != p) && (header != p); } int disordered() const;//是否已经有序 ListNodePosi(T) find(T const& e) const{//无序列表查找 return find(e, _size, trailer); } ListNodePosi(T) find(T const& e, int n, ListNodePosi(T) p)const;//无序区间查找 ListNodePosi(T) search(T const& e) const{//有序列表查找 return search(e, _size, trailer); } ListNodePosi(T) search(T const& e, int n, ListNodePosi(T) p)const;//有序区间查找 ListNodePosi(T) selectMax(ListNodePosi(T), int n);//在p及其n-1各后继中选出最大者 ListNodePosi(T) selectMax(){ return selectMax(header->succ, _size); }//整体最大者 //可写访问接口 ListNodePosi(T) insertAsFirst(T const & e);//将e作为首节点插入 ListNodePosi(T) insertAsLast(T const& e);//将e作为末节点插入 ListNodePosi(T) insertA(ListNodePosi(T) p, T const& e);//将e作为p的后继插入(after) ListNodePosi(T) insertB(ListNodePosi(T) p, T const& e);//将e作为p的前驱插入(before) T remove(ListNodePosi(T) p);//删除合法位置p处的节点,返回被删除节点 void merge(List<T>& L){ merge(first(), size, L, L.first, L._size); }//全列表归并 void sort(ListNodePosi(T) p, int n);//列表区间排序 void sort(){ sort(first(), _size); }//整体排序 int deduplicate();//无序去重 int uniquify();//有序去重 void reverse();//前后倒置 void traverse(void(*)(T&));//遍历,visit操作 (函数指针) template<typename VST> void traverse(VST&);//遍历,依次实施visit操作(函数对象)};//List//类函数的定义//初始化template <typename T>void List<T>::init(){ header = new ListNode<T>(); trailer = new ListNode<T>(); header->succ = trailer; trailer->pred = trailer; _size = 0;}//无序表的查找template <typename T>ListNodePosi(T) List<T>::find(T const& e, int n, ListNodePosi(T) p) const{ while (0 < n--){//对于p的n个最近的真前驱,从右向左 if (e == (p = p->pred)->data) return p;//逐个比对,直至命中或越界 } return NULL;//p越界意味着失败}//失败时返回NULL//作为首节点插入template <typename T> ListNodePosi(T) List<T>::insertAsFirst(T const& e){ _size++; return header->insertAsSucc(e);//e当做首节点插入}//作为末节点插入template <typename T>ListNodePosi(T) List<T>::insertAsLast(T const& e){ _size++; return trailer->insertAsPred(e);//e当做末节点插入}//作为当前节点的后继插入template <typename T>ListNodePosi(T) List<T>::insertA(ListNodePosi(T) p, T const& e){ _size++; return p->insertAsSucc(e);//e当做p的后继插入}//作为当前节点的前驱插入template <typename T>ListNodePosi(T) List<T>::insertB(ListNodePosi(T) p, T const& e){ _size++; return p->insertAsPred(e);//e当做p的前继插入}//基本接口template <typename T>void List<T>::copyNodes(ListNodePosi(T) p, int n){ init();//创建头、尾节点并做初始化 while (n--){//将起自p的n项依次作为末节点插入 insertAsLast(p->data); p = p->succ; }}//重载下标操作符,以通过秩直接访问列表节点(虽方便,效率低,需慎用)template <typename T>ListNodePosi(T) List<T>::operator[] (Rank r) const{ ListNodePosi(T) p = first();//从首节点出发 while (0 < r--)p = p->succ;//顺数第r个节点即是 return p;//目标节点,返回其中所存元素}//重载构造函数template <typename T>List<T>::List(List<T> const & L){ copyNodes(L.first(), L._size);}template <typename T>List<T>::List(List<T> const & L, int r, int n){ copyNodes(L[r], n);}//删除合法节点p,返回其数值template <typename T>T List<T>::remove(ListNodePosi(T) p){ T e = p->data;//备份待删除节点的数值(假定T类型可直接赋值) p->pred->succ = p->succ; p->succ->pred = p->pred;//后继、前驱 delete p; _size--;//释放节点,更新规模 return e;//返回备份的数值}//析构函数template <typename T>List<T>::~List(){ clear(); delete header; delete trailer;}//清空列表template <typename T>int List<T>::clear(){ int oldSize = _size; while (0 < _size)//反复删除首节点,直至表为空 remove(header->succ); return oldSize;}//剔除无序列表中的重复节点template <typename T>int List<T>::deduplicate(){ if (_size < 2)return 0;//平凡列表自然无重复 int oldSize = _size;//记录原始规模 ListNodePosi(T) p = header; Rank r = 0;//p从首节点开始 while (trailer != (p = p->succ)){//依次直到末节点 ListNodePosi(T) q = find(p->data, r, p);//在p的r个真前驱中查找雷同者 q ? remove(q) : r++;//若的确存在,则删除之,否则秩加一 }//assert:循环过程中的任意时刻p的所有前驱互不相同 return oldSize - _size;//列表规模变化量,即被删除元素的总数}//借助函数指针机制遍历template <typename T>void List<T>::traverse(void(*visit)(T&)){ for (ListNodePosi(T) p = header->succ; p != trailer; p = p->succ) visit(p->data);}//操作器 借助函数对象机制遍历template <typename T> template<typename VST>void List<T>::traverse(VST& visit){ for (ListNodePosi(T) p = header->succ; p != trailer; p = p->succ) visit(p->data);}//有序列表去重template <typename T> int List<T>::uniquify(){ if (_size < 2)return 0; int oldSize = _size; ListNodePosi(T) p = first(); ListNodePosi(T) q; while (trailer != (q = p->succ)){ if (p->data != q->data) p = q; else remove(q); } return oldSize - _size;}//只需要遍历整个列表一趟,O(n)//在有序表内p节点的n个真前驱中找到不大于e的最后者template <typename T>ListNodePosi(T) List<T>::search(T const&e, int n, ListNodePosi(T) p)const{ //assert:0<=n<=Rank(p)<_size do{ p = p->pred; n--; } while ((-1 < n) && (e < p->data));//逐个比较直到命中或者越界 return p;}//失败时,返回区间左边界的前驱(可能是header)//列表的选择排序算法:对起始于位置p的n个元素排序template<typename T>void List<T>::selectionSort(ListNodePosi(T) p, int n){ ListNodePosi(T) head = p->pred; ListNodePosi(T) tail = p; for (int i = 0; i < n; i++)tail = tail->succ;//待排序区间(head,tail) while (1 < n){ ListNodePosi(T) max = selectMax(head->succ, n); insertB(tail, remove(max)); tail = tail->pred; n--; }}//从起始位置p的n个元素中选出最大者template<typename T>ListNodePosi(T) List<T>::selectMax(ListNodePosi(T) p, int n){ ListNodePosi(T) max = p; for (ListNodePosi(T) cur = p; 1 < n; n--){ if (!lt((cur = cur->succ)->data, max->data)) max = cur; } return max;}//a小于b?template<typename T>bool lt(T a, T b){ return a < b;}//列表的插入排序算法:对起始于位置p的n个元素排序template<typename T>void List<T>::insertionSort(ListNodePosi(T) p, int n){ for (int r = 0; r < n; r++){ insertA(search(p->data, r, p), p->data); p = p->succ; remove(p->pred); }}//有序列表的归并:当前列表中自p起的n个元素,与列表L中自q起的m个元素归并template <typename T>void List<T>::merge(ListNodePosi(T) & p, int n, List<T>&L, ListNodePosi(T) q, int m){ ListNodePosi(T) pp = p->pred;//借助前驱,以便返回前。。。 while (0 < m){//在q尚未移出区间之前 if ((0 < n) && (p->data <= q->data)){//若p仍在区间内且v(p)<=v(q),则 if (q == (p = p->succ))//p归入合并的列表,并替换为其直接后继 break; n--; } else{//若p已经超出了右界或者v(q)<v(p),则 insertB(p, L.remove((q = q->succ)->pred));//将q转移至p之前 m--; } } p = pp->succ;//确定归并后区间的(新)起点}//列表的归并排序算法:对于起始于位置p的n个元素排序template<typename T>void List<T>::mergeSort(ListNodePosi(T) &p, int n){ if (n < 2) return;//若待排序范围已足够小,则直接返回;否则... int m = n >> 1;//以中点为界 ListNodePosi(T) q = p; for (int i = 0; i < m; i++)q = q->succ;//均分列表 mergeSort(p, m); mergeSort(q, n - m);//对前、后子列表分别排序 merge(p, m, *this, q, n - m);//归并}//注意:排序后,p依然指向归并后区间的(新)起点//判断列表是否有序template<typename T>int List<T>::disordered()const{ int n=0; for (ListNodePosi(T) p = header->succ; p->succ != trailer; p = p->succ){ if (p->data > p->succ->data) n++; } return n;}//返回0表示已有序#endif // !LIST_H
这里先给出List的实现,以后再介绍Vector,List等数据结构的具体应用。
0 0
- 【二】数据结构之List
- Redis数据结构详解之List(二)
- Redis数据结构详解之List(二)
- Redis数据结构详解之List(二)
- 数据结构之“Ordered List and Sorted List”(二)
- java数据结构之List
- 数据结构List之ArrayList
- 数据结构List之Vector
- 数据结构List之LinkedList
- 数据结构之List
- 数据结构之vector&list
- Libevent分解之数据结构List
- 数据结构之list(用链表实现)
- Python基础数据结构之list
- Redis的数据结构之List
- scala数据结构之List列表
- 数据结构之二
- 数据结构之---树(二)
- Impala与Hive的比较
- 编程之美-2.14 求数组的子数组之和的最大值
- bzoj 1180 LCT
- 欢迎使用CSDN-markdown编辑器
- poj 2528 线段树 离散化()
- 【二】数据结构之List
- 时间日期格式转换
- 二叉树的镜像
- 基于QT的五子棋音乐部分功能
- sql语句
- 【Question】I/O函数
- GCD队列绑定NSObject类型上下文数据-利用__bridge_retained(transfer)转移内存管理权
- Http请求
- java二进制、八进制、十六进制间转换详细