欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++实现数据结构——单链表

程序员文章站 2022-06-23 13:17:27
2020年8月7日 周五 天气晴 【不悲叹过去,不Install Package荒废现在,不惧怕未来】本文目录1. 引言2. 主文件——main.cpp3. 单链表类.h文件——linklist.h4. 单链表类.cpp文件——linklist.cpp5. 预编译头文件——stdafx.h参考文献1. 引言用C++实现了简单的单链表类,功能包括插入、删除、查找相关元素,分离链表等操作。代码是用VS2019实现的,每个函数的功能都添加了一定注释,完整工程放在了我的github上,有需要的也可以自取。...

2020年8月7日 周五 天气晴 【不悲叹过去,不荒废现在,不惧怕未来】



1. 引言

用C++实现了简单的单链表类,功能包括插入、删除、查找相关元素,分离链表等操作。代码是用VS2019实现的,每个函数的功能都添加了一定注释,完整工程放在了我的github上,有需要的也可以自取。

github地址:https://github.com/March225/Data-structure-implemented-by-Cpp


2. 主文件——main.cpp

/**
 *  @Copyright (C) 2020 March. All rights reserved.
 *  @license   GNU General Public License (GPL)
 *  @author	   March
 *  @email	   345916208@qq.com
 *  @file	   main.cpp
 *  @brief	   单链表的C++实现主文件
 *  @version   1.0
 *  @date	   2020-08-07
 */

#include "stdafx.h"
#include "linklist.h"

int main()
{
	FILE* stream1;
	ios::sync_with_stdio(false); // 让c风格的输入输出流和c++的输入输出流分开,使cin读入的更快
	freopen_s(&stream1, "10_1.in", "r", stdin); // 直接从文档中读取待输入的数据


	// 下面展示的是按照元素值的奇偶性分解单链表的功能,实现函数为 SplitLinkListByParityOfVal()
	LinkList* L1 = new LinkList();
	int len;
	cin >> len;
	L1->CreateLinkListByInsertAtEnd(len);
	L1->PrintLinkList();

	LinkList* L1_odd = new LinkList();
	LinkList* L1_even = new LinkList();

	L1->SplitLinkListByParityOfVal(L1_odd, L1_even); // 实现分离
	L1_odd->PrintLinkList(); // 打印奇数部分链表
	L1_even->PrintLinkList(); // 打印偶数部分链表

	L1->PrintLinkList(); // 打印原链表(由于原链表已经分解,因此打印出来为空)

	delete L1;
	delete L1_odd;
	delete L1_even;

	return 0;
}

3. 单链表类.h文件——linklist.h

#pragma once
/**
 * @brief 创建一个单链表类
 */

class LinkList
{
public:
	LinkList();
	~LinkList();

	int GetLength(); // 返回单链表的长度
	bool GetElemByPosition(int pos, ElemType& val); // 根据位置返回单链表的元素
	bool CreateLinkListByInsertAtEnd(int len); // 尾插法创建单链表
	bool CreateLinkListByInsertAtBeg(int len); // 头插法创建单链表
	bool InsertElemBeforePosition(int pos, ElemType val); // 在第pos个结点前插入值为val的结点
	bool FindElemByValue(int& pos, ElemType val); // 返回单链表中值为val的元素位置
	bool DeleteElemByPosition(int pos); // 根据位置删除单链表的元素
	bool InsertElemInOrder(ElemType val); // 在一个有序单链表中插入元素,并保证链表还是有序的
	bool SplitLinkListByParityOfVal(LinkList*& l_odd, LinkList*& l_even); // 根据元素的奇偶性分离单链表
	void PrintLinkList(); // 打印单链表的长度和元素

private:
	ListNode* head_; // 单链表的哑结点
	int length_; // 单链表的长度
};

4. 单链表类.cpp文件——linklist.cpp

#include "stdafx.h"
#include "linklist.h"

// 构造函数,初始化单链表
LinkList::LinkList() :head_(nullptr), length_(0)
{
	cout << this << "单链表已被初始化!" << endl;
}

// 析构函数,销毁单链表
LinkList::~LinkList()
{
	while (head_)
	{
		ListNode* cur = head_;
		head_ = head_->next;
		delete cur;
	}
	cout << this << "单链表已被销毁!" << endl;
}

// 返回单链表的长度
int LinkList::GetLength()
{
	return length_;
}

// 根据位置返回单链表的元素
bool LinkList::GetElemByPosition(int pos, ElemType& val)
{
	if (head_ == nullptr) {
		cout << "单链表为空,获取元素失败!" << endl;
		return false;
	}
	else if (pos <= 0 || pos > length_) {
		cout << "位置 " << setw(2) << pos << " 有误!" << "获取元素失败!" << endl;
		return false;
	}
	else {
		ListNode* cur = head_;
		while (cur)
		{
			if (--pos == 0) {
				val = cur->val;
				return true;
			}
			cur = cur->next;
		}
		cout << "未知原因,获取元素失败!" << endl;
		return false;
	}
}

// 尾插法创建单链表
bool LinkList::CreateLinkListByInsertAtEnd(int len)
{
	ListNode* dummy_node = new ListNode(0), * cur = dummy_node;
	for (int i = 0; i < len; ++i)
	{
		ElemType num;
		cin >> num;
		ListNode* new_node = new ListNode(num);
		cur->next = new_node;
		cur = cur->next;
		++length_;
	}
	head_ = dummy_node->next;
	return true;
}

// 头插法创建单链表
bool LinkList::CreateLinkListByInsertAtBeg(int len)
{
	ListNode* cur = nullptr;
	for (int i = 0; i < len; ++i)
	{
		ElemType num;
		cin >> num;
		ListNode* new_node = new ListNode(num);
		new_node->next = cur;
		cur = new_node;
		++length_;
	}
	head_ = cur;
	return true;
}

// 在第pos个结点前插入值为val的结点
bool LinkList::InsertElemBeforePosition(int pos, ElemType val)
{
	if (head_ == nullptr) {
		cout << "单链表为空,插入元素失败!" << endl;
		return false;
	}
	else if (pos <= 0 || pos > length_) {
		cout << "位置 " << setw(2) << pos << " 有误!" << "插入元素失败!" << endl;
		return false;
	}
	else {
		ListNode* dummy_node = new ListNode(0), * cur = dummy_node;
		dummy_node->next = head_;
		while (cur->next) {
			if (--pos == 0) {
				ListNode* tmp = cur->next;
				cur->next = new ListNode(val);
				cur->next->next = tmp;

				head_ = dummy_node->next;
				++length_;
				return true;
			}
			cur = cur->next;
		}
		cout << "未知原因,插入元素失败!" << endl;
		return false;
	}
}

// 返回单链表中值为val的元素位置
bool LinkList::FindElemByValue(int& pos, ElemType val)
{
	if (head_ == nullptr) {
		cout << "单链表为空,查找元素失败!" << endl;
		return false;
	}

	ListNode* cur = head_;
	int cnt = 1;
	while (cur) {
		if (cur->val == val) {
			pos = cnt;
			return true;
		}
		++cnt;
		cur = cur->next;
	}
	cout << "没有查找到值为 " << val << " 的元素!" << endl;
	return false;
}

// 根据位置删除单链表的元素
bool LinkList::DeleteElemByPosition(int pos)
{
	if (head_ == nullptr) {
		cout << "单链表为空,删除元素失败!" << endl;
		return false;
	}
	else if (pos <= 0 || pos > length_) {
		cout << "位置 " << setw(2) << pos << " 有误!" << "删除元素失败!" << endl;
		return false;
	}
	else {
		ListNode* dummy_node = new ListNode(0), * cur = dummy_node;
		dummy_node->next = head_;
		while (cur->next) {
			if (--pos == 0) {
				ListNode* tmp = cur->next;
				cur->next = cur->next->next;
				delete tmp;

				head_ = dummy_node->next;
				--length_;
				return true;
			}
			cur = cur->next;
		}
		cout << "未知原因,删除元素失败!" << endl;
		return false;
	}
}

// 在一个有序单链表中插入元素,并保证链表还是有序的
bool LinkList::InsertElemInOrder(ElemType val)
{
	if (!head_) {
		head_ = new ListNode(val);
		++length_;
		return true;
	}

	ListNode* dummy_node = new ListNode(0);
	dummy_node->next = head_;
	ListNode* pre = dummy_node;
	while (pre->next) {
		if (val <= pre->next->val) {
			ListNode* tmp = pre->next;
			pre->next = new ListNode(val);
			pre->next->next = tmp;
			break;
		}
		else {
			if (!pre->next->next) {
				ListNode* cur = pre->next;
				cur->next = new ListNode(val);
				cur->next->next = nullptr;
				break;
			}
			else
				pre = pre->next;
		}
	}
	head_ = dummy_node->next;
	++length_;
	return true;
}

// 根据元素的奇偶性分离单链表
bool LinkList::SplitLinkListByParityOfVal(LinkList*& l_odd, LinkList*& l_even)
{
	ListNode* cur = head_;
	ListNode* dummy_node_odd = new ListNode(0), * dummy_node_even = new ListNode(0);
	ListNode* cur_odd = dummy_node_odd, * cur_even = dummy_node_even;

	while (cur) {
		if (cur->val % 2 == 1) {
			cur_odd->next = cur;
			cur = cur->next;
			cur_odd->next->next = nullptr;
			cur_odd = cur_odd->next;
			++l_odd->length_;
		}
		else {
			cur_even->next = cur;
			cur = cur->next;
			cur_even->next->next = nullptr;
			cur_even = cur_even->next;
			++l_even->length_;
		}
		
	}
	l_odd->head_ = dummy_node_odd->next;
	l_even->head_ = dummy_node_even->next;
	head_ = nullptr;
	length_ = 0;
	return true;
}

// 打印单链表的长度和元素
void LinkList::PrintLinkList()
{
	ListNode* cur = head_;
	cout << "单链表长度:" << length_ << endl;
	cout << "单链表元素:";
	while (cur)
	{
		cout << cur->val << "->";
		cur = cur->next;
	}

	cout << "nullptr" << endl << endl;
}

5. 预编译头文件——stdafx.h

#pragma once
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#if !defined(AFX_STDAFX_H__D36E9D40_3BCB_4A85_9D48_AC876E7A2942__INCLUDED_)
#define AFX_STDAFX_H__D36E9D40_3BCB_4A85_9D48_AC876E7A2942__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <bits/stdc++.h> // 万能的头文件,可能需要手动加入include文件夹中

typedef int ElemType; // 使链表的数据类型ElemType为int

/**
 * @brief 定义单链表的结点
 */
struct ListNode {
	ElemType val;
	ListNode* next;
	ListNode() : val(0), next(nullptr) {}
	ListNode(int x) : val(x), next(nullptr) {}
};

using namespace std;

#endif // !defined(AFX_STDAFX_H__D36E9D40_3BCB_4A85_9D48_AC876E7A2942__INCLUDED_)

参考文献

https://www.cnblogs.com/25th-engineer/p/9937678.html

本文地址:https://blog.csdn.net/m0_37433111/article/details/107864737