数据结构(邓俊辉):列表及相关概念

  1. 链表节点的ADT接口
    在这里插入图片描述列表节点模板类:
typedef 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);
};
  1. 链表的ADT接口
    在这里插入图片描述列表的形式:头尾结点始终存在,但不可见(需要封装),由他们(header->succ或者trailer->pred)来寻找链表;首末节点及其中间的节点可见。
    在这里插入图片描述
    列表的模板类:
typedef 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);
};

# 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);//从p开始连续的n项归并排序
	void selectionSort(ListNodePosi(T), int);
	void insertionSort(ListNodePosi(T), int);
	
public:
	//构造函数
	List() {init();}
	List(List<T> const& L);//整体复制链表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;}
	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, int n, ListNodePosi(T) p ) const; //有序区间查找
	ListNodePosi(T) selectMax ( ListNodePosi(T) p, 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 ( header->succ, _size, L, L.header->succ, 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操作(函数对象,可全局性修改)
};
  1. 链表的实现
    (1)默认构造函数
    链表初始化:
template <typename T> 
void List<T> :: init() {
	header = new ListNode<T>;
	trailer = new ListNode<T>;
	header->succ = trailer; header->pred = NULL;
	trailer->pred = header; trailer->succ = NULL;
	_size = 0;
} 

(2)寻秩访问,重载操作符[]

template <typename T>
T& List<T> :: operator[] (Rank r) const {
	ListNodePosi(T) p = first();
	while(0 < r--)
		p = p->succ;
	return p->data;
}

寻秩访问效率太低。

(3)查找
使用区间查找:find(e,p,n) p的n个前驱中寻找。
区间查找的特例是:find(e)

template <typename T>
ListNodePosi(T) List<T> :: find(T const& e, int n, ListNodePosi(T) p) const {
	while(0 < n--)
		if(e == (p = p->pred)->data)
			return p;
	return NULL;
}

(4)插入
多种插入方法:

template<typename T>
ListNodePosi(T) List<T> :: insertAsFirst (T const& e){
	_size++; 
	return head->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) ListNodePosi<T> :: insertA (ListNodePosi(T) p, T const& e){
	_size++; 
	return p->insertAsSucc(e);//e作为p的后继插入
}

template<typename T>
ListNodePosi(T) ListNodePosi<T> :: insertB (ListNodePosi(T) p, T const& e){
	_size++; 
	return p->insertAsPred(e);//e作为p的前驱插入
}

前驱插入:

template<typename T>
ListNodePosi(T) ListNode<T> :: insertAsPred(T const& e){
	ListNodePosi(T) x = new ListNode(e, pred, this);
	pres->succ = x; pred = x;//this.pred->succ = x; this.pred = x;
	return x;
}

在这里插入图片描述其中(3)和(4)的步骤不能反,因为链表不能断。

后继插入:

template<typename T>
ListNodePosi(T) ListNode<T> :: insertAsSucc(T const& e){
	ListNodePosi(T) x = new ListNode(e, this, succ);
	succ->pred = x; succ = x;
	return x;
}

(5)链表的复制构造

template<typename T>
void List<T> :: copyNOdes(ListNodePosi(T) p, int n){
	init();
	while(n--){
		insertAsLast(p->data);
		p = p->succ;
	}
}

(6)删除

template <typename T>
T List<T> :: remove (ListNodePosi(T) p){
	T e = p->data;//备份
	p->pred->succ = p->succ; p->succ->pred = p->pred;
	delete p;
	_size--;
	return e;
}

(7)析构

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(head->succ);
	return oldSize;
}

(8)删除重复元素
1)列表:

template <typename T>
int List<T> :: deduplicate(){
	if(_size < 2)
		return 0;
	int oldSize = _size;
	ListNodePosi(T) p = header; Rank r = 0;
	while(trailer != (p = p->succ)){
		ListNodePosi(T) q = find(p->data, r, p);
		q ? remove(q) : r++;
	}
	return oldSize - _size;
}

2)有序列表

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;
}

(9)遍历

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);
}

(10)查找

template <typename T>
ListNodePosi(T) List<T> :: search(T const& e, int n, ListNodePosi(T) p) const{
	while (0 <= n--)
		if (((p = p->pred)->data) <= e) break;
	return p;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值