单向链表模版实现(c++)

本文详细介绍了单向链表的概念,包括节点结构、链表类LinkedList的实现,包括插入、删除、查找和修改节点功能,以及主函数中的测试实例。
摘要由CSDN通过智能技术生成

关于单向链表

单向链表是链表最常用的一种,一个列表节点有两个字段,即数据域和指针域。在单向链表中,指向第一个节点的节点称为“头结点”,最后一个节点的指针域设为null。
在这里插入图片描述
如图即是{1,3,1,4,5,2,1}存在在单向链表的示意图,头节点数据域为null,指向首节点(数据域为1),首节点指向下一个节点,一直到最后一个节点,指向null。1部分是3部分的前驱节点,3部分是1部分的后驱节点。

1.已知列表的每一个节点有数据域和指针域组成,故定义一个节点结构体ListNode:

struct ListNode{
	eleType data;
	ListNode *next;
	ListNode(eleType ele) : data(ele), next(nullptr) {}
};

解释: data表示数据域,*next表示下一个节点(后继节点)。ListNode(eleType ele) : data(ele), next(nullptr) {}构造函数,在声明节点对象的时候,将ele赋值给data,next节点设置为空。

2.接下来建立一个链表类LinkedList:

class LinkedList{
private:
	ListNode *head;
	int size;
public:
	LinkedList() : head(nullptr), size(0) {}
	~LinkedList();
	//增删改查
	void insertToIndex(int index,eleType element); //增
	void removeByIndex(int index); //删
	ListNode* getListNodeByIndex(int index); //改
	void updateListNodeByIndex(int index,eleType value); //差
	void printList(); //打印
};

解释: 该类有两个私有成员,*head表示头节点,size表示链表长度,在构造函数中分别初始化为null和0,表示是一个空表。定义了析构函数,在后面实现。另声明了该类的增删改查函数。

3.实现析构函数,在销毁链表时调用:

/*定义一个游标节点,从头节点出发,遍历,赋值给tmp,执行删除*/
   LinkedList::~LinkedList(){
	ListNode *curr = head;
	while (curr != nullptr) {
		ListNode *tmp = curr;
		curr = curr->next;
		delete tmp;
	}
}     

4.插入函数实现

void LinkedList::insertToIndex(int index, eleType element){
	if(index < 0 || index > size)
		throw out_of_range("Invalid position");
	ListNode *newNode = new ListNode(element);
	if(index == 0){
		newNode->next = head;
		head = newNode;
	}else{
		ListNode *curr = head;
		for(int i = 0; i < index - 1; ++ i){
			curr = curr->next;
		}
		newNode->next = curr->next;
		curr->next = newNode;
	}
	++ size;
}		

解释: 传入index以及要插入的元素,首先进行下表越界判断,抛出异常。之后通过ListNode创建一个新节点,如果要插入位置为头节点,就让新节点指向头节点,将头节点赋值给新节点。如果插入位置不是头节点,则建立一个游标节点curr,循环遍历至要插入的位置的前一个节点,之后把新节点指向这个位置的后一个节点,再让这个位置的后继节点等于新节点。最后size加一。

5.删除函数实现

void LinkedList::removeByIndex(int index){
	if(index < 0 || index > size)
		throw out_of_range("Invalid position");
	ListNode *curr = head;
	for(int i = 0; i < index - 1; ++ i){
		curr = curr->next;
	}
	ListNode *temp = curr->next;
	curr->next = temp->next;
	delete temp;
	-- size;
}

解释: 传入index表示要删除节点的位置,首先进行下表合法校验。之后同样建立游标节点,遍历至要删除位置的前一个节点,然后建立一个临时节点保存要删除的节点,在让curr的后继节点指向tmp的后继节点,之后删除tmp。

5.查找函数实现

	ListNode*  LinkedList::getListNodeByIndex(int index){
	if(index < 0 || index > size)
		throw out_of_range("Invalid position");
	ListNode *curr = head;
	for(int i = 0; i < index;i++){
		curr = curr->next;
	}
	return curr;
}

解释 该函数返回的是一个节点类型,首先进行下表判断,之后遍历至要返回的位置,返回该节点即可。

6.修改函数实现

void LinkedList::updateListNodeByIndex(int index,eleType value){
	if(index < 0 || index > size)
		throw out_of_range("Invalid position");
	getListNodeByIndex(index)->data = value;
};

解释该函数返回值为空,直接调用查找函数找到对应节点,之后修改其指针域为对应值即可。

主函数测试

	int main(){
	LinkedList list;
	list.insertToIndex(0, 33);
	list.insertToIndex(1, 33);
	list.insertToIndex(2, 33);
	list.updateListNodeByIndex(2, 66);
	//list.removeByIndex(0);
	list.printList();
	cout<<list.getListNodeByIndex(0)->data;
}
/*
结果:
33 33 66 
---------------------
33
*/
完整程序
#include <iostream>
#include<stdexcept>
using namespace std;

#define  eleType int

struct ListNode{
	eleType data;
	ListNode *next;
	
	ListNode(eleType ele) : data(ele), next(nullptr) {}
};
class LinkedList{
private:
	ListNode *head;
	int size;
public:
	LinkedList() : head(nullptr), size(0) {}
	~LinkedList();
	void insertToIndex(int index,eleType element);
	void removeByIndex(int index);
	ListNode* getListNodeByIndex(int index);
	void updateListNodeByIndex(int index,eleType value);
	void printList();
};
LinkedList::~LinkedList(){
	ListNode *curr = head;
	while (curr != nullptr) {
		ListNode *tmp = curr;
		curr = curr->next;
		delete tmp;
	}
}
void LinkedList::insertToIndex(int index, eleType element){
	if(index < 0 || index > size)
		throw out_of_range("Invalid position");
	ListNode *newNode = new ListNode(element);
	if(index == 0){
		newNode->next = head;
		head = newNode;
	}else{
		ListNode *curr = head;
		for(int i = 0; i < index - 1; ++ i){
			curr = curr->next;
		}
		newNode->next = curr->next;
		curr->next = newNode;
	}
	++ size;
}
void LinkedList::removeByIndex(int index){
	if(index < 0 || index > size)
		throw out_of_range("Invalid position");
	ListNode *curr = head;
	for(int i = 0; i < index - 1; ++ i){
		curr = curr->next;
	}
	ListNode *temp = curr->next;
	curr->next = temp->next;
	delete temp;
}
	ListNode*  LinkedList::getListNodeByIndex(int index){
		if(index < 0 || index > size)
			throw out_of_range("Invalid position");
		ListNode *curr = head;
		for(int i = 0; i < index;i++){
			curr = curr->next;
		}
		return curr;
	}
void LinkedList::updateListNodeByIndex(int index,eleType value){
	if(index < 0 || index > size)
		throw out_of_range("Invalid position");
	getListNodeByIndex(index)->data = value;
};

void LinkedList::printList(){
	ListNode *curr = head;
	while (curr != nullptr) {
		cout<<curr->data<<' ';
		curr = curr->next;
	}
	cout<<"\n---------------------\n";
}
int main(){
	LinkedList list;
	list.insertToIndex(0, 33);
	list.insertToIndex(1, 33);
	list.insertToIndex(2, 33);
	list.updateListNodeByIndex(2, 66);
	//list.removeByIndex(0);
	list.printList();
	cout<<list.getListNodeByIndex(0)->data;
}
面向对象程序设计课程作业 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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值