双向链表
来源:互联网 发布:python截取中文字符串 编辑:程序博客网 时间:2024/06/05 14:50
/*protected: void init() 列表创建时的初始化 int clear() 清除所有节点 void copyNodes ( nodePos(T), int ) 复制列表中自位置p起的n项 void merge ( nodePos(T)&, int, List<T>&, ListNodePosi(T), int ) 归并 void mergeSort ( nodePos(T)&, int ) 对从p开始连续的n个节点归并排序 void selectionSort ( nodePos(T), int ) 对从p开始连续的n个节点选择排序 void insertionSort ( nodePos(T), int ) 对从p开始连续的n个节点插入排序public:构造函数 List() 默认 List ( List<T> const& L ) 整体复制列表L List ( List<T> const& L, Rank r, int n ) 复制列表L中自第r项起的n项 List ( nodePos(T) p, int n ) 复制列表中自位置p起的n项析构函数 ~List() 释放(包含头、尾哨兵在内的)所有节点只读访问接口 Rank size() const 规模 bool empty() const 判空 T& operator[] ( Rank r ) const 重载,支持循秩访问(效率低) nodePos(T) first() const 首节点位置 nodePos(T) last() const 末节点位置 bool valid ( nodePos(T) p ) 判断位置p是否对外合法 int disordered() const 判断列表是否已排序 nodePos(T) find ( T const& e ) const 无序列表查找 nodePos(T) find ( T const& e, int n, nodePos(T) p ) const 无序区间查找 nodePos(T) search ( T const& e ) const 有序列表查找 nodePos(T) search ( T const& e, int n, nodePos(T) p ) const 有序区间查找 nodePos(T) selectMax ( nodePos(T) p, int n ) 在p及其n-1个后继中选出最大者 nodePos(T) selectMax() 整体最大者可写访问接口 nodePos(T) insertAsFirst ( T const& e ) 将e当作首节点插入 nodePos(T) insertAsLast ( T const& e ) 将e当作末节点插入 nodePos(T) insertAfter ( nodePos(T) p, T const& e ) 将e当作p的后继插入 nodePos(T) insertBefore ( nodePos(T) p, T const& e ) 将e当作p的前驱插入 T remove ( ListNodePosi(T) p ) 删除合法位置p处的节点,返回被删除节点 void merge ( List<T>& L ) 全列表归并 void sort ( nodePos(T) p, int n ) 列表区间排序 void sort() 列表整体排序 int deduplicate() 无序去重 int uniquify() 有序去重 void reverse() 前后倒置遍历 void traverse ( void (* ) ( T& ) ) 遍历,依次实施visit操作(函数指针,只读或局部性修改) template <typename VST> void traverse ( VST& ) 遍历,依次实施visit操作(函数对象,可全局性修改) */#include <cstdlib>#include <cmath>//列表节点位置#define nodePos(T) node<T>*//秩typedef int Rank;//less thantemplate <typename T>static bool lt ( T& a, T& b ) { return a < b;}//列表节点template <typename T>struct node { // 成员 T data; nodePos(T) pred; nodePos(T) succ; // 构造函数 //针对header和trailer的构造 node() {} //默认构造器 node ( T e, nodePos(T) p = NULL, nodePos(T) s = NULL ) : data ( e ), pred ( p ), succ ( s ) {} // 操作接口 nodePos(T) insertAsPred ( T const& e ){ nodePos(T) x = new node ( e, pred, this ); pred->succ = x; pred = x; return x; } nodePos(T) insertAsSucc ( T const& e ){ nodePos(T) x = new node ( e, this, succ ); succ->pred = x; succ = x; return x; }};//列表template <typename T>class list {private: //规模 int _size; //头哨兵 nodePos(T) header; //尾哨兵 nodePos(T) trailer;protected: //列表初始化,在创建列表对象时统一调用 void init(){ //创建头哨兵节点 header = new node<T> //创建尾哨兵节点 trailer = new node<T> //连接指针 header->succ = trailer; header->pred = NULL; trailer->pred = header; trailer->succ = NULL; //记录规模 _size = 0; } //清空列表 int clear(){ int oldSize = _size; //反复删除首节点,直至列表变空 while ( 0 < _size ) remove ( header->succ ); return oldSize; } //p合法,且至少有n-1个真后继节点 void copyNodes ( nodePos(T) p, int n){ //创建头、尾哨兵节点并做初始化 init(); //将起自p的n项依次作为末节点插入 while ( n-- ) { insertAsLast ( p->data ); p = p->succ; } } void merge ( nodePos(T)& p, int n, list<T>& L, nodePos(T) q, int m){// assert: this.valid(p) && rank(p) + n <= size && this.sorted(p, n)// L.valid(q) && rank(q) + m <= L._size && L.sorted(q, m)// 注意:在归并排序之类的场合,有可能 this == L && rank(p) + n = rank(q) nodePos(T) pp = p->pred; //借助前驱(可能是header),以便返回前 ... while ( 0 < m ) //在q尚未移出区间之前 if ( ( 0 < n ) && ( p->data <= q->data ) ) //若p仍在区间内且v(p) <= v(q),则 { if ( q == ( p = p->succ ) ) break; n--; } //p归入合并的列表,并替换为其直接后继 else //若p已超出右界或v(q) < v(p),则 { insertB(p, L.remove((q = q->succ)->pred)); m--; } //将q转移至p之前 p = pp->succ; //确定归并后区间的(新)起点 } void mergeSort ( nodePos(T)& p, int n){ //valid(p) && rank(p) + n <= size //若待排序范围已足够小,则直接返回;否则... if ( n < 2 ) return; //以中点为界 int m = n >> 1; nodePos(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依然指向归并后区间的(新)起点 void selectionSort ( nodePos(T) p, int n){ //valid(p) && rank(p) + n <= size nodePos(T) head = p->pred; nodePos(T) tail = p; //待排序区间为(head, tail) for ( int i = 0; i < n; i++ ) tail = tail->succ; //在至少还剩两个节点之前,在待排序区间内 while ( 1 < n ) { //找出最大者(歧义时后者优先) nodePos(T) max = selectMax ( head->succ, n ); //将其移至无序区间末尾(作为有序区间新的首元素) insertB(tail, remove(max)); tail = tail->pred; n--; } } void insertionSort ( nodePos(T) p, int n){ //valid(p) && rank(p) + n <= size //逐一为各节点 for ( int r = 0; r < n; r++ ) { //查找适当的位置并插入 insertA(search(p->data, r, p), p->data); //转向下一节点 p = p->succ; remove ( p->pred ); } }public: // 构造函数 //默认 list() { init(); } list ( list<T> const& L ){ copyNodes ( L.first(), L._size ); } list ( list<T> const& L, Rank r, int n ){ copyNodes ( L[r], n ); } list ( nodePos(T) p, int n ){ copyNodes ( p, n ); } // 析构函数 ~list(){ clear(); delete header; delete trailer; } // 只读访问接口 //规模 Rank size() const { return _size; } //判空 bool empty() const { return _size <= 0; } T& operator[] ( Rank r ) const{ //assert: 0 <= r < size //从首节点出发 nodePos(T) p = first(); //顺数第r个节点即是 while ( 0 < r-- ) p = p->succ; //目标节点,返回其中所存元素 return p->data; } //首节点位置 nodePos(T) first() const { return header->succ; } //末节点位置 nodePos(T) last() const { return trailer->pred; } //判断位置p是否对外合法 bool valid ( nodePos(T) p ) { //将头、尾节点等同于NULL return p && ( trailer != p ) && ( header != p ); } //统计逆序相邻元素对的总数 int disordered() const{ int n = 0; node<T>* p = first(); for ( int i = 0; i < _size - 1; p = p->succ, i++ ) if ( p->data > p->succ->data ) n++; return n; } //无序列表查找 nodePos(T) find ( T const& e ) const { return find ( e, _size, trailer ); } nodePos(T) find ( T const& e, int n, nodePos(T) p ) const{ //(0 <= n <= rank(p) < _size)对于p的最近的n个前驱,从右向左 //逐个比对,直至命中或范围越界 while ( 0 < n-- ) if ( e == ( p = p->pred )->data ) return p; //p越出左边界意味着区间内不含e,查找失败 //失败时,返回NULL return NULL; } //有序列表查找 nodePos(T) search ( T const& e ) const{ return search ( e, _size, trailer ); } nodePos(T) search ( T const& e, int n, nodePos(T) p ) const{ // assert: 0 <= n <= rank(p) < _size //对于p的最近的n个前驱,从右向左逐个比较 while ( 0 <= n-- ) //直至命中、数值越界或范围越界 if ( ( ( p = p->pred )->data ) <= e ) break; // assert: 至此位置p必符合输出语义约定——尽管此前最后一次关键码比较可能没有意义(等效于与-inf比较) //返回查找终止的位置 return p; } //失败时,返回区间左边界的前驱(可能是header)——调用者可通过valid()判断成功与否 nodePos(T) selectMax ( nodePos(T) p, int n ){ //最大者暂定为首节点p nodePos(T) max = p; //从首节点p出发,将后续节点逐一与max比较 for ( nodePos(T) cur = p; 1 < n; n-- ) //若当前元素不小于max,则 if ( !lt ( ( cur = cur->succ )->data, max->data ) ) //更新最大元素位置记录 max = cur; //返回最大节点位置 return max; } //整体最大者 nodePos(T) selectMax() { return selectMax ( header->succ, _size ); } // 可写访问接口 nodePos(T) insertAsFirst ( T const& e ){ _size++; return header->insertAsSucc ( e ); } //e当作首节点插入 nodePos(T) insertAsLast ( T const& e ){ _size++; return trailer->insertAsPred ( e ); } //e当作末节点插入 nodePos(T) insertA ( nodePos(T) p, T const& e ){ _size++; return p->insertAsSucc ( e ); } //e当作p的后继插入(After) //e当作p的前驱插入(Before) nodePos(T) insertB ( nodePos(T) p, T const& e ){ _size++; return p->insertAsPred ( e ); } //删除合法节点p,返回其数值 T remove ( nodePos(T) p ){ //备份待删除节点的数值(假定T类型可直接赋值) T e = p->data; //后继、前驱 p->pred->succ = p->succ; p->succ->pred = p->pred; //释放节点,更新规模 delete p; _size--; //返回备份的数值 return e; } //全列表归并 void merge ( list<T>& L ) { merge ( this->header->succ, this->_size, L, L.first(), L._size ); } //列表区间排序 void sort ( nodePos(T) p, int n ){ //随机选取排序算法。可根据具体问题的特点灵活选取或扩充 switch ( rand() % 3 ) { //插入排序 case 1: insertionSort ( p, n ); break; //选择排序 case 2: selectionSort ( p, n ); break; //归并排序 default: mergeSort ( p, n ); break; } } //列表整体排序 void sort() { sort ( first(), _size ); } //剔除无序列表中的重复节点 int deduplicate(){ //平凡列表自然无重复 if ( _size < 2 ) return 0; //记录原规模 int oldSize = _size; //p从首节点开始 nodePos(T) p = header; Rank r = 0; //依次直到末节点 while ( trailer != ( p = p->succ ) ) { //在p的r个(真)前驱中查找雷同者 nodePos(T) q = find ( p->data, r, p ); //若的确存在,则删除之;否则秩加一 q ? remove ( q ) : r++; } //assert: 循环过程中的任意时刻,p的所有前驱互不相同 //列表规模变化量,即被删除元素总数 return oldSize - _size; } //成批剔除重复元素,效率更高 int uniquify(){ //平凡列表自然无重复 if ( _size < 2 ) return 0; //记录原规模 int oldSize = _size; //p为各区段起点,q为其后继 nodePos(T) p = first(); nodePos(T) q; //反复考查紧邻的节点对(p, q) while ( trailer != ( q = p->succ ) ) //若互异,则转向下一区段 if ( p->data != q->data ) p = q; //否则(雷同),删除后者 else remove ( q ); //列表规模变化量,即被删除元素总数 return oldSize - _size; } //前后倒置 void reverse(){ //头、尾节点 nodePos(T) p = header; nodePos(T) q = trailer; //(从首、末节点开始)由外而内,逐对地交换对称节点的数据项 for ( int i = 1; i < _size; i += 2 ) std::swap( ( p = p->succ )->data, ( q = q->pred )->data ); } // 遍历 void traverse ( void (*visit ) ( T& ) ){ //遍历,依次实施visit操作(函数指针,只读或局部性修改) for ( nodePos(T) p = header->succ; p != trailer; p = p->succ ) visit ( p->data ); } template <typename VST> //操作器 //遍历,依次实施visit操作(函数对象,可全局性修改) void traverse ( VST& visit ){ for ( nodePos(T) p = header->succ; p != trailer; p = p->succ ) visit ( p->data ); }};
阅读全文
0 0
- SzNOI 双向约瑟夫(双向链表)
- 双向链表&&堆栈
- 双向链表
- 使用双向链表
- 双向链表
- 双向循环链表
- 双向循环链表
- 双向链表
- 实现双向链表
- 双向循环链表
- 建立双向链表
- 双向链表
- 双向链表
- 双向循环链表
- 双向链表
- 链表-双向链表
- 双向链表
- 双向动态链表
- 2.基础知识Android消息处理机制
- Android 嵌套滑动机制(NestedScrolling)
- SQL查询和优化(九)
- 北大方正声誉不佳,人寿保险业务巨亏
- visual studio 2015下载地址
- 双向链表
- springMVC拦截器执行过程和使用
- bayes
- ES6 generator 与 koa 中间件 是如何 generator解决异步的
- 每日MySQL之017:MySQL中的prepared statements
- ThreadPoolExecutor使用小结
- geronimo
- 串口透传(转自天运科技)
- 多线程之原子锁