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

关于单向链表

单向链表是链表最常用的一种,一个列表节点有两个字段,即数据域和指针域。在单向链表中,指向第一个节点的节点称为"头结点",最后一个节点的指针域设为null。

如图即是{1,3,1,4,5,2,1}存在在单向链表的示意图,头节点数据域为null,指向首节点(数据域为1),首节点指向下一个节点,一直到最后一个节点,指向null。1部分是3部分的前驱节点,3部分是1部分的后驱节点。

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

c 复制代码
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:

c 复制代码
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.实现析构函数,在销毁链表时调用:

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

4.插入函数实现

c 复制代码
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.删除函数实现

c 复制代码
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;
}

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

5.查找函数实现

c 复制代码
	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.修改函数实现

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

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

主函数测试

c 复制代码
	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
*/
完整程序
c 复制代码
#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 小时前
AAC ADTS 帧结构信息
网络·数据结构·ffmpeg·音视频·aac
艾莉丝努力练剑1 小时前
【C++:异常】C++ 异常处理完全指南:从理论到实践,深入理解栈展开与最佳实践
java·开发语言·c++·安全·c++11
Zsy_0510037 小时前
【数据结构】二叉树OJ
数据结构
快乐zbc7 小时前
【C++ 基础】:给定一个指针 p,你能判断它是否指向合法的对象吗?
c++
sulikey8 小时前
C++类和对象(下):初始化列表、static、友元、内部类等核心特性详解
c++·static·初始化列表·友元·匿名对象·内部类·编译器优化
oioihoii9 小时前
C++网络编程:从Socket混乱到优雅Reactor的蜕变之路
开发语言·网络·c++
程序员东岸9 小时前
《数据结构——排序(中)》选择与交换的艺术:从直接选择到堆排序的性能跃迁
数据结构·笔记·算法·leetcode·排序算法
程序员-King.9 小时前
day104—对向双指针—接雨水(LeetCode-42)
算法·贪心算法
笨鸟要努力9 小时前
Qt C++ windows 设置系统时间
c++·windows·qt
牢七9 小时前
数据结构11111
数据结构