模拟list(列表)

// 模拟list
#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;

//#define node<T> list_node<T>*;
#define ptr_node list_node<T>*
template<typename T> struct list_node
{
	T data;
	ptr_node pre;
	ptr_node suc;
	list_node(){}                             // 针对head和tail构造,根据语义,这两个不需要赋data值
	list_node(T e,ptr_node p=NULL,ptr_node s=NULL):data(e),pre(p),suc(s){}
	//ptr_node insert_as_pre(ptr_node p);    // 是插数据,大哥!
	ptr_node insert_as_pre(T const& e);      // 返回该元素的插入处的节点指针
	ptr_node insert_as_suc(T const& e);
};
template<typename T> ptr_node list_node<T>::insert_as_pre(T const& e)   //以下两个返回被插入的位置
{
	ptr_node temp = new list_node<T>(e);
	this->pre->suc = temp;
	temp->suc = this;

	temp->pre = this->pre;
	this->pre = temp;
	return temp;
}
template<typename T> ptr_node list_node<T>::insert_as_suc(T const& e)
{
	ptr_node temp = new list_node<T>(e);
	// 链表的后插与前插是不一样的
	temp->suc = this->suc;
	temp->pre = this;

	this->suc->pre = temp;
	this->suc = temp;
	return temp;
}
/**************************************************************************************/
template<typename T>
struct Func_visit
{
	int add_num;
	Func_visit(int n):add_num(n){}
	void operator()(T& e)     //这里用引用,否则局部变量又会销毁!!!
	{
		e += add_num;
	}
};
template<typename T> class list
{
private:
	int size; ptr_node head; ptr_node tail;
public:
	list() { init(); }                  // 无参构造后size,head,tail默认=0
				// 拷贝构造函数,对列表的整体复制    list(list<T> const& L) ERROR?yes!不要总想着拷贝构造函数的const&
	list(list<T>& L)	  // cause:此错误可能是由于调用对象上的非 const 成员函数导致的 const 异常
	{
		//copy_nodes(head->suc, size);   //想扇死你,完全没有理解拷贝的含义
		copy_nodes(L.first(), L.size);
	}
	~list()               // 包括头节点和尾节点全部删除   
	{
		cout << "destructor" << endl;
		clear();
		delete head;
		delete tail;
	}

	void init();
	void copy_nodes(ptr_node pos, int n);  // 从pos开始(包括pos),复制n个结点
	ptr_node first();         // getfirst() 看着不舒服,仍然是返回指针类型(即位置)为后续函数调用
	ptr_node last();
								// 注意:这里的插入有两个位置
	ptr_node insert(T const& e,ptr_node pos);      //e作为pos的前驱插入
	ptr_node insert(ptr_node pos, T const& e);     // 作为后继插入
	ptr_node insert_as_first(T const& e);        // 便于阅读,后面就不会错
	ptr_node insert_as_last(T const& e);
	ptr_node find(T const& e, int n, ptr_node pos);      // 从当前位置往前查找n个元素
	int dedupilate();                         // 唯一化
	int Size();
	void reverse();
	T operator[](int r)const;  //ptr_node operator[](int r);  // 脑子再次短路,重载下标运算符当然是返回元素的值了
	T remove(ptr_node pos);      // 删除p处的节点,返回元素的值

	//ptr_node select_max(list const& List);  本来就在里面,传你妈的傻逼参数
	ptr_node search(T const& e, int n, ptr_node pos)const;
	ptr_node select_max(ptr_node pos,int n);      // n表示n个元素
	void selection_sort(ptr_node pos, int n);    // 从pos开始的连续n个节点,即一共n个元素
	void insertion_sort(ptr_node p, int n);
	int uniquify();								// 有序列表唯一化
	//void traverse(void(visit*)(T&));
	void traverse1(void(*visit)(T&));
	template<typename VST> void traverse2(VST& func_visit);
	void show_list();
	int clear();                // 返回清除元素的个数
	
	
};
template<typename T>void list<T>::init()
{
	head = new list_node<T>;
	tail = new list_node<T>;
	head->pre = NULL; head->suc = tail;
	tail->pre = head; tail->suc = NULL;
	size = 0;
}
template<typename T> void list<T>::copy_nodes(ptr_node pos, int n)
{
	init();   // 这里就相当于对要拷贝的列表赋值了,head和tail节点都给出了,接下来只需拷贝即可
	while (n--)
	{
		insert_as_last(pos->data);
		pos = pos->suc;
	}
}
template<typename T> ptr_node list<T>::first()
{
	return head->suc;
}
template<typename T> ptr_node list<T>::last()
{
	return tail->pre;
}
template<typename T>ptr_node list<T>::insert_as_first(T const& e)
{
	return insert(e, first());
}
template<typename T>ptr_node list<T>::insert_as_last(T const& e)
{
	return insert(last(), e);
}
template<typename T>ptr_node list<T>::insert(T const& e, ptr_node pos)
{
	size++;
	return pos->insert_as_pre(e);
}
template<typename T>ptr_node list<T>::insert(ptr_node pos, T const& e)
{
	size++;
	return pos->insert_as_suc(e);
}
template<typename T> ptr_node list<T>::find(T const& e, int n, ptr_node pos)
{
	while (n--)
	{
		if ((pos = pos->pre)->data == e)
			return pos;
	}
	return NULL;
}
template<typename T> int list<T>::dedupilate()
{
	int old_size = size;
	int steps = 1;
	//for (ptr_node behind = first(), front = first()->suc; front != tail; front = front->suc)  // 快慢指针
	// 上面这样写就gg了,front就不是指针类型了
	ptr_node behind;
	ptr_node front;
	for (behind = first(), front = first()->suc; front != tail; front = front->suc)
	{
		ptr_node pos = find(front->data, steps, front);
		if (pos != NULL)   // 在pos的地方找到了
			remove(pos);
		else
			steps++;
	}
	return old_size - size;
}
template<typename T> T list<T>::operator[](int r)const
{
	// 关于这个数数问题,自己比划比划
	ptr_node ptr = head->suc;
	while (r-- > 0)
		ptr = ptr->suc;
	return ptr->data;
}
template<typename T> int list<T>::Size()            // 别与size重名了('~')
{
	return size;
}
template<typename T> void list<T>::reverse()
{
	ptr_node front = first();
	ptr_node behind = last();
	//while (front != behind || front->suc != behind)   // 这就说明你的逻辑有问题
	while(front!=behind && front->suc!=behind)
	{
		// 交换两个指针的数据
		T temp = front->data;
		front->data = behind->data;
		behind->data = temp;
		front = front->suc;
		behind = behind->pre;
	}
}
template<typename T> T list<T>::remove(ptr_node pos)    // 假定可以删除
{
	T temp = pos->data;
	pos->pre->suc = pos->suc;
	pos->suc->pre = pos->pre;
	size--;
	delete pos;
	return temp;
}
template<typename T>void list<T>::show_list()
{
	ptr_node ptr = head->suc;
	int length = size;
	while (length-- > 0)                   // --length就完犊子了,少了一个
	{
		cout << ptr->data << " ";
		ptr = ptr->suc;
	}
	cout << endl;
}
template<typename T>ptr_node list<T>::search(T const& e, int n, ptr_node pos)const
{
	// 返回不超过e的最靠右元素
	ptr_node ptr = pos->pre;
	for (int i = 0; i<n && ptr->data>e;i++,ptr=ptr->pre)
	{

	}
	return ptr;
	// 插入的时候要在ptr后面插

}
template<typename T>ptr_node list<T>::select_max(ptr_node pos,int n)
{
	// 要保证语义,从pos开始,(包括pos)一共n个节点
	ptr_node temp = pos;
	for (int i = 1; i < n; ++i)
	{
		temp = temp->suc;
	}
	ptr_node ptr = temp;   // 从后往前扫描
	// 每个节点都要遍历,共n次
	while (n>0)
	{
		if (ptr->data > temp->data)
		{
			temp = ptr;
		}
		ptr = ptr->pre;
		n--;
	}
	//cout << "max=" << temp->data;
	return temp;
}
template<typename T>void list<T>::selection_sort(ptr_node pos, int n)
{
	ptr_node ptr = tail;
	while (n>0)
	{
		ptr_node max_item = select_max(first(),n);
		//cout <<"max="<< max_item->data;
		ptr->insert_as_pre(max_item->data);
		remove(max_item);
		ptr = ptr->pre;
		n--;
		// 这一步很重要,注意接口之间的关系
		size++;
	}
}
template<typename T>void list<T>::insertion_sort(ptr_node p, int n)
{
	// n-1次
	for (int r=0;r<n;++r)
	{
		 //ptr位置,不包括ptr,往前数r个元素
		insert(search(p->data,r,p),p->data);  // 插的语义很重要!!!事先规定好,否则浪费时间
		p = p->suc;
		remove(p->pre);
		//size++;
	}
}
template<typename T> int list<T>::uniquify()
{
	if (size < 2)
		return 0;
	int old_size = size;
	ptr_node behind = first();
	ptr_node front = behind->suc;
	while (front != tail)
	{
		if (behind->data == front->data) {
			behind = behind->suc;
			remove(behind->pre);
		}
		behind = front;
		front = front->suc;
	}
	return old_size - size;
	
}
template<typename T> void visit(T& e)
{
	e += 3;
}
//template<typename T> void list<T>::traverse(visit)// 怎么还没有理解,参数是函数指针照样写,只是传参数的时候用visit罢了
template<typename T> void list<T>::traverse1(void(*visit)(T&))
{
	for (ptr_node ptr = first(); ptr != tail; ptr = ptr->suc)
		visit(ptr->data);
}
template<typename T> template<typename VST>
void list<T>::traverse2(VST& func_visit)
{
	for (ptr_node ptr = first(); ptr != tail; ptr = ptr->suc)
		func_visit(ptr->data);
}
template<typename T>int list<T>::clear()
{
	//int cnt = 0;  // 我感觉自己的脑子有点问题
	int old_size = size;
	while (size>0)                // 这里又出问题了,remove接口已经将size--了,你怕是在梦游
	{
		//ptr_node ptr = head->suc;
		ptr_node ptr = tail->pre;
		remove(ptr);
	}
	return old_size;
}

int main()
{
	list<int> list1;
	
	// insert(i,first) first只能往前插,同理insert(last,i) last只能往后插
	for (int i = 0; i < 6; ++i)
	{
		//my_list.insert(i,my_list.first());
		list1.insert(list1.last(),i+3);
	}
	list1.insert(list1.first(), 7);
	list1.insert(list1.first(), 5);
	list1.insert(list1.last(), 5);
	cout << "list1:";
	list1.show_list();
	/*list1.dedupilate();*/
	/*for (int i = 0; i < list1.Size(); ++i)
	{
		cout << "my_list[" << i << "]=" << list1[i] << endl;
	}*/
	cout << "list2:";
	list<int> list2(list1);
	list2.show_list();
	cout << "list2.sort:";
	//list2.selection_sort(list2.first(),list2.Size());
	list2.insertion_sort(list2.first(), list2.Size());
	list2.show_list();
	cout << "list2.reverse:";
	list2.reverse();
	list2.show_list();
	//list2.traverse(visit);
	//list2.traverse2(Func_visit<int>(5));
	// 你又忘了呀!!!
	/*Func_visit<int>func_add(50);
	list2.traverse2(func_add);
	cout << "list2.traverse:";*/
	cout << "list2.uniquify:";
	list2.uniquify();
	list2.show_list();
	list2.clear();
	cout << "list2.size="<<list2.Size() << endl;	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值