C++链表类

本文探讨如何使用C++类实现双向链表,包括元素结构、头尾指针、常见函数如查找、删除、插入的实现。通过内存申请优化插入元素的时间复杂度,但可能引入空间浪费。文中留有指针相关BUG供读者发现并解决。
摘要由CSDN通过智能技术生成

链表是一种线性数据结构,占用不连续的内存,用一个或两个指针(或元素的代号)保存与其相邻的元素。

怎么用类实现一个链表呢?(这里我们讨论双向链表


首先,我们可以建一个数组,保存各元素,只不过元素的顺序不一定是按照下标排列的。

元素可以用一个结构体表示,它有三个元素:数值、上一个元素的指针、下一个元素的指针。

 

然后,要添加头指针和尾指针,以确定头和尾的位置。

 

接着,我们最好考虑一下各函数的实现,以免出现一些问题。

  1. 构造函数。构造函数可以把数组中的全部元素都用上吗?显然不能。因为这样就无法往里面插入新的元素了。只能初始化一部分或全不初始化。
  2. 输入/输出函数。这一部分实不实现都行,如果一定要实现,按照指针依次寻找就行了。
  3. 查找元素函数。根据链表的性质,它的时间复杂度最快只能是O(n)。这也一样,按照指针依次寻找就行了。
  4. 删除元素函数。这也很简单,把相邻元素的指针修改一下就行了。
  5. 插入元素函数。第一步,要找到一个不用的元素,这就需要再建一个数组,用来标记有没有用过,再加入一个循环,选择第一个不用的元素,如果全用过了,那就不插入或报错。第二步,修改相邻元素的指针。

根据以上几点,我们要再建一个数组表示是否用过。

代码如下:

#ifndef BASIC_LINKED_LIST
#define BASIC_LINKED_LIST
#include<iostream>
#include<cstdio>
using namespace std;
#ifndef MAX_SIZE
	#define MAX_SIZE 1003
#endif
//macros
#ifdef FOR_LIST
	#define for_list(list_name,type,ptr_name)\
				list_element<type> *ptr_name=list_name.head;\
				for(;p!=list_name.tail;p=p->next)
	#define for_list_reverse(list_name,type,ptr_name)\
				list_element<type> *ptr_name=list_name.tail;\
				for(;p!=list_name.head;p=p->pre)
#endif
#ifdef DEFINE_TYPE
	#define def_list_ele(type,name) typedef list_element<type> name
	#define def_plist_ele(type,name) typedef list_element<type>* name
	#define def_list(type,name) typedef basic_linked_list<type> name
#endif
//list_element class
template<typename T>
class list_element{
	public:
	T data;
	list_element *next,*pre;
}; 
//basic_linked_list class
template<typename T>
class basic_linked_list{ //Without new/delete.The name of a linked list class with new/delete will be "linked_list".
	public:
	list_element<T> datas[MAX_SIZE];
	bool used[MAX_SIZE];
	list_element<T> *head,*tail;
	//constructors
	basic_linked_list(){ // WARNING: The datas in this list will be RANDOM !!! And there is NO PLACE to INSERT !!!
		datas[0].next=&datas[1],datas[0].pre=0,used[0]=1,head=datas;
		int stsz_cut1=MAX_SIZE-1; //st==start,sz==size,cut1=="minus 1"
		for(int i=1;i<stsz_cut1;i++){
			datas[i].next=&datas[i+1],datas[i].pre=&datas[i-1],used[i]=1;
		}
		datas[stsz_cut1].next=0,datas[stsz_cut1].pre=&datas[stsz_cut1-1],used[stsz_cut1]=1,tail=&datas[stsz_cut1];
	}
	basic_linked_list(int start_size){ // WARNING: The datas in this list will be RANDOM !!!
		datas[0].next=&datas[1],datas[0].pre=0,used[0]=1,head=datas;
		int stsz_cut1=start_size-1; //st==start,sz==size,cut1=="minus 1"
		for(int i=1;i<stsz_cut1;i++){
			datas[i].next=&datas[i+1],datas[i].pre=&datas[i-1],used[i]=1;
		}
		datas[stsz_cut1].next=0,datas[stsz_cut1].pre=&datas[stsz_cut1-1],used[stsz_cut1]=1,tail=&datas[stsz_cut1];
	}
	basic_linked_list(T start_data,int start_size){ //if start_size==5 : 0/1/2/3/4 can be used
		datas[0].data=star
面向对象程序设计课程作业 1. 请创建一个数据型为T的链表模板List,实现以下成员函数: 1) 默认构造函数List(),将该链表初始化为一个空链表(10分) 2) 拷贝构造函数List(const List& list),根据一个给定的链表构造当前链表(10分) 3) 析构函数~List(),释放链表中的所有节点(10分) 4) Push_back(T e)函数,往链表最末尾插入一个元素为e的节点(10分) 5) operator<<()友元函数,将链表的所有元素按顺序输出(10分) 6) operator=()函数,实现两个链表的赋值操作(10分) 7) operator+()函数,实现两个链表的连接,A=B+C(10分) 2. 请编写main函数,测试该模板的正确性: 1) 用List模板定义一个List型的模板对象int_listB,从键盘读入m个整数,调用Push_back函数将这m个整数依次插入到该链表中;(4分) 2) 用List模板定义一个List型的模板对象int_listC,从键盘读入n个整数,调用Push_back函数将这n个整数依次插入到该链表中;(4分) 3) 用List模板定义一个List型的模板对象int_listA,调用List的成员函数实现A = B + C;(4分) 4) 用cout直接输出int_listA的所有元素(3分) 5) 用List模板定义List型的模板对象double_listA, double_listB, double_listC,重复上述操作。(15分) 3. 输入输出样例: 1) 输入样例 4 12 23 34 45 3 56 67 78 3 1.2 2.3 3.4 4 4.5 5.6 6.7 7.8 2) 输出样例 12 23 34 45 56 67 78 1.2 2.3 3.4 4.5 5.6 6.7 7.8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值