单链表实现(C++)

概念

        单链表由结点(Node)组成,结点中有一个数据域和一个指针域,数据域存放结点中的数据的数值,指针域存放指向下一个结点的地址,我们所实现的单链表是带有头结点的单链表,头节点与其他结点不同,头结点中的数据域赋值为0或单链表长度等特性信息。

        链式存储线性表时,不需要使用地址的连续存储单元,即不要求逻辑上相邻元素在物理地址上也相邻,它通过“链”建立起数据元素之间的逻辑关系,因此插入和删除元素操作不需要移动元素,而只需要修改指针,但也会失去顺序表可随机存取的优点。

C++代码实现

所实现的单链表为带有头结点的单链表,索引从0开始,存储的值为正值。

创建List.h的头文件,定义单链表结构体以及可实现操作的函数声明。代码如下:

#pragma once//防止重复包含头文件
#include <iostream>
using namespace std;
class LinkList {
private:
	class Node {
	public:
		int data = 0;
		Node *next = nullptr;
	};
	Node *head;
	int length = 0;
public:
	LinkList();//构造函数

	void create(int n);//初始化n个结点的单链表

	void print();//打印单链表中的数据

	int getLength();//获取单链表的长度

	void isEmpty();//判断此单链表是否为空

	//默认index从0开始

	int search(int index);//查找索引为index的数值并返回

	int find(int elem);//查找数值为elem的索引并返回

	void insertByIndex(int index, int data);//在索引为index之前的位置插入数值为data的结点

	void deleteByIndex(int index);//删除索引为index的结点
};

创建List.cpp的源文件,编写头文件函数的具体实现:

#include "List.h"
//LinkList::表示LinkList类作用域下
LinkList::LinkList() {
	head = new Node;
	head->data = 0;
	head->next = nullptr;
	int length = 0;
}
int LinkList::getLength(){
	cout << "链表中的元素个数为:" << length << endl;
	return length;
}
void LinkList::create(int n) {
	Node *p = head;
	length = n;
	for (int i = 0;i < n;i++)
	{
		cout << "请输入第" << i << "个结点的数据:";
		Node *cur = new Node;
		cin >> cur->data;
		p->next = cur;
		p = cur;
		cur->next = nullptr;
		i++;
	}
}
void LinkList::print(){
	Node *cur = head->next;
	if (!length) {
		cout << "链表为空!" << endl;
		return;
	}
	cout << "链表中的元素为:" << endl;
	while (cur) {
		cout << cur->data << " ";
		cur = cur->next;
	}
	cout << endl;
}
void LinkList::isEmpty(){
	if (!length) {
		cout << "链表为空~" << endl;
		return;
	}
	cout << "链表不为空" << ",";
	this->getLength();
}
int LinkList::search(int index){ //认为索引从0开始
	if (index < 0 && index >= length)
		cout << "索引输入错误!" << endl;
	else {
		Node *temp = head->next;
		int i = 0;
		while (temp) {
			if (i == index) {
				cout << "链表中索引为" << index << "的数据为" << temp->data << endl;
				return temp->data;
			}
			else {
				i++;
				temp = temp->next;
			}
		}
	}
	return -1;//假定链表中不存入负数
}
int LinkList::find(int elem){
	Node *cur = head->next;
	int index = 0;
	while (cur) {
		if (cur->data == elem)
			return index;
		else {
			cur = cur->next;
			index++;
		}
	}
	cout << elem << "不在链表中!" << endl;
	return -1;
}
void LinkList::insertByIndex(int index, int data) { //在index之前插入数据为data的结点
	if (index < 0 && index >= length) {
		cout << "索引位置不合法" << endl;
	}
	else {
		Node *cur = head;
		int pos = 0;
		while (pos != index) {
			cur = cur->next;
			pos++;
		}
		Node *temp = new Node;
		temp->data = data;
		temp->next = cur->next;
		cur->next = temp;
		length++;
		cout << data << "插入成功!" << endl;
	}
}
void LinkList::deleteByIndex(int index) {
	if (index < 0 && index >= length) {
		cout << "索引输入错误!" << endl;
	}
	else {
		Node *cur = head;
		int pos = 0;
		while (pos != index) {
			cur = cur->next;
			pos++;
		}
		Node *temp = cur->next;
		cur->next = temp->next;
		delete temp;
		length--;
		cout << "删除成功!" << endl;
	}
}

创建单链表.cpp的源文件,测试所写的单链表各功能:

#include "List.h"
#include <iostream>
using namespace std;
void test() {
	LinkList list;//创建链表结构体对象
	cout << "请输入链表中结点的个数:";
	int n;
	cin >> n;
	list.create(n);
	list.print();
	list.getLength();
	list.isEmpty();
	cout << "请输入需要查询的索引位置:";
	int index;
	cin >> index;
	list.search(index);
	cout << "请输入需要查询的数据:";
	int elem;
	cin >> elem;
	if (list.find(elem) != -1) {
		cout << elem << "在链表中的索引位置是" << list.find(elem) << endl;
	}
	cout << "请输入需要插入结点的位置索引和数值:";
	int pos, data;
	cin >> pos >> data;
	list.insertByIndex(pos, data);
	list.print();
	list.getLength();
	cout << "请输入需要删除的结点索引:";
	int deleteIndex;
	cin >> deleteIndex;
	list.deleteByIndex(deleteIndex);
	list.print();
	list.getLength();
}
int main() {
	test();
	system("pause");
	return 0;
}

核心代码详解

void LinkList::create(int n) {
	Node *p = head;
	length = n;
	for (int i = 0;i < n;i++)
	{
		cout << "请输入第" << i << "个结点的数据:";
		Node *cur = new Node;
		cin >> cur->data;
		p->next = cur;
		p = cur;
		cur->next = nullptr;
		i++;
	}
}

上述代码为创建一个长度为n的链表的函数,传参n赋值给链表长度变量length。

1、创建节点指针变量p,并将头结点head的地址赋值给p,此时p与head指向同一块内存空间,对p操作就是对head操作;

2、for循环,依次录入节点;

3、new Node在堆区创建节点指针cur;

4、读入数值并赋值给cur->data;

5、将p的next指针指向cur的地址,此时对p操作了,也即head的next指针也指向cur的地址;

6、将cur的地址赋值给p节点,此时因为head创建在堆区,其地址并不会改变,此时p与cur指向同一块内存空间,对p操作就是对cur操作;

7、cur节点的next指针指向空

8、i++进入下一个输入节点入链

9、 new Node在堆区创建节点指针cur;(这里要理解这次创建的cur与上一次创建的cur地址不同,你可以理解为上一次创建的是cur1,这一次是cur2);

10、读入数值并赋值给cur2->data;

11、将p的next指针指向cur2的地址,此时对p操作了,也即cur1的next指针也指向cur2的地址;

12、将cur2的地址赋值给p节点,此时因为cur1创建在堆区,其地址并不会改变,此时p与cur2指向同一块内存空间,对p操作就是对cur2操作;

.

.

.

相信这两次循环你便能理解这个函数的具体实现过程,理解了这个函数的实现过程,再去看单链表的完整代码,理解起来定然事半功倍。

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值