C++单向链表怎么实现 -数据结构

这篇文章我给大家介绍用C++语言实现单向链表
大家可以把代码复制到自己的编译器里,运行一下。,首先建立三个文件main.cpp ChainList.h ChainList.cpp
(其中的注释及讲解都在代码里.废话不多说,直接上代码。)

1,ChainList.h 文件

#pragma once

struct Node
{
	int data;
	Node* pNext;
};

class ChainList
{
public:
	//构造函数
	ChainList ();

	//返回链表的长度
	int	  getlength ();

	//在pos位置插入da这个数据,使da成为第pos个数据
	void insertData (int pos,int da);

	//依次插入, 
	void pushBack (int dat);

	//打印链表数据
	void printList ();

	//删除数据da
	void deleteData (int da);
	
	//析构函数
	~ChainList ();

private:
	//找到da数据并返回 目标数据的位置,这个借口不必向外部提供,所以把它设为private
	int findData (int da);

private:
	Node* head;
	int length;
};


2. ChainList.cpp 文件

#include "ChainList.h"
#include<iostream>
using namespace std;

//构造函数
ChainList::ChainList ()
{
	//node节点的默认值为-3,和nullptr
	Node* pNew = new Node { -3,NULL };
	this->length = 0;//长度为零
	head = pNew;//把构造好的头结点赋给head,一个链表只有一个头结点
}

//返回链表的长度
int ChainList::getlength ()
{
	return this->length;//直接return就好了
}

//根据位置插入数据,成功返回true
void ChainList::insertData (int pos,int da)
{
	//情况一
	if ( pos > this->length )//如果输入的pos太大,则把它当做最后一个数据,也就是在this->length插入da
	{
		pos = this->length;
	}
	//情况二
	else if ( pos == this->length ){//如果pos恰好等于链表的长度的话,就相当于在链表的最后面插入da
		 pushBack (da);
		 return;
	}
	//情况三

	Node* pNew = new Node { da,NULL };//新建一个节点放数据da
	Node* previous = head,* next = head->pNext;
	for ( int i = 0; i < pos-1; i++ )
		previous = previous->pNext;//找到pos位置之前的一个节点

	Node* tmp = previous->pNext;//要删除的节点tmp
	next = previous->pNext->pNext;//next是pos之后的那一个节点
	
	previous->pNext = pNew;//安排previous,next,pNew 三个节点的指向关系
	pNew->pNext = next;

	tmp->pNext = nullptr;//把tmp的pNext指针指向空
	delete tmp;//把tmp申请的内存空间释放
}

//依次向后插入数据
void ChainList::pushBack (int dat)
{
	Node* tp = head;//由头节点开始遍历
	for ( int i = 0; i < this->length; i++ )
	{
		tp = tp->pNext;
	}//循环结束后tp就指向最后一个节点了

	Node* pNew = new Node { dat,NULL };
	tp->pNext = pNew;//tp指向新节点pNew,那么pNew就是最后一个节点了

	this->length++;//别忘了链表的长度要加1
}

 

//找到数据并返回 目标数据的位置
int ChainList::findData (int da)
{
	Node* tp = head;
	for ( int i = 0; i < this->length; i++ )//遍历链表,找到数据和da一样的节点,并且返回该节点在链表的位置
	{
		if(tp->data==da){
			return i;
		}
		else
			tp = tp->pNext;
	}
	/*为什么要再判断一次呢,因为要查找的数据是最后一个的时候,那么当i=(this->length)-1的时候,
	判断tp->data是否等于da,答案是不等于,所以执行了else里面的语句,之后i++,跳出循环,
	少判断了一次i=this->length的情况,所以要补上一次判断*/
	if ( tp->data==da )
		return this->length;
	else
		return -1;//遍历整个链表都找不到的话,就返回-1
	
}

//打印链表的数据
void ChainList::printList ()
{
	Node* tmp = head;

	if ( tmp==nullptr )//如果链表为空,那么提示出这句话
	{
		cout << "该链表为空" << endl;
		return;
	}
	for ( int i = 0; i < this->length; i++ )//依次遍历并且打印
	{
		tmp = tmp->pNext;//先移到下一个,因为头结点是构造链表的时候默认的值,我们用不到,头结点相当于一个摆设,只负责链表入口的作用
		cout <<tmp->data << "  ";
	}
	cout << endl;
}

//删除da这个数据
void ChainList::deleteData (int da)
{
	if ( da== -3 )//情况一,如果是-3,这说明删除的是头结点
	{
		cout << "不能删除链表的头结点" << endl;
		return;
	}
	int pos2 = findData (da);//找到这个数据在链表里面是第几号
 
	//情况二,链表里面没有da这个数据
	if ( pos2 == -1 )//没找到的时候返回-1
	{
		cout << "=======对不起:没找到该数据 " << da<<"=======" << endl;
		return	;
	}
	//情况三,要删除的数据是该链表的最后一个节点
	else if ( pos2 == this->length )
	{
		Node* tmp = head;
		for ( int i = 0; i < pos2; i++ )
		{
			tmp = tmp->pNext;
		}
		tmp->pNext = NULL;
	}
	//情况四,删除的是链表中普通的一个节点(不是头结点,也不是尾节点)
	else{
		Node* previous = head,* next = nullptr;
		for ( int i = 0; i < pos2-1; i++ )
		{
			previous = previous->pNext;
		}
		Node* tmp = previous->pNext;//tmp是目标节点
		next = previous->pNext->pNext;//找到目标节点的前后两个节点
		previous->pNext = next;
		delete tmp;
	}

	this->length--;
	return;
}

ChainList::~ChainList ()
{
	ChainList::~ChainList ()
{
	if ( head==NULL )//如果链表的头节点为空的话,那么直接return;
	{
		return;
	}
	 
	Node* tmp = head;//这就好比一个清洁组长(tmp2)带着一个清洁工(tmp)开始清洁卫生,
	//tmp2指到哪里,tmp就清洁哪里
	Node* tmp2 = head->pNext;
	while ( tmp2 )//只要tmp2有地方指,tmp就有地方打扫
	{
		delete tmp;
		tmp = tmp2;
		tmp2 = tmp2->pNext;
	}//最后tmp2没地方指了(指向NULL),退出循环.. 
	delete tmp;//虽然tpm2没有地方指了,但是还得删除一次tmp,此时tmp指向的是最后一个节点

	head = NULL;//释放完了head指针指向的空间,把head指针指向空
	length = 0;// 析构结束之后,链表的长度也设为零
}

}

3,main.cpp

#include<iostream>
#include "ChainList.h"
using namespace std;


void t5 ()
{
 
	ChainList cl;
	cl.pushBack (17);
	cl.pushBack (10);
	cl.pushBack (4);
	cl.pushBack (15);
	cl.pushBack (13);
	cl.pushBack (11);

	cout << "链表的长度为:" << cl.getlength () << endl;
	cout << "打印链表数据:"; cl.printList (); cout << endl;
	cl.deleteData (4);

	cout << "------------------------\n";
	cout << "链表的长度为:" << cl.getlength () << endl;
	cout << "打印链表数据:"; cl.printList (); cout << endl;

	cl.insertData (3,100);
	cout << "------------------------\n";
	cout << "链表的长度为:" << cl.getlength () << endl;
	cout << "打印链表数据:"; cl.printList (); cout << endl;

	cl.deleteData (11);
	cout << "------------------------\n";
	cout << "链表的长度为:" << cl.getlength () << endl;
	cout << "打印链表数据:"; cl.printList (); cout << endl;

	cl.insertData (cl.getlength (),1000);
	cout << "------------------------\n";
	cout << "链表的长度为:" << cl.getlength () << endl;
	cout << "打印链表数据:"; cl.printList (); cout << endl;

}

//==========================================
int main ()
{
	t5 ();

	return 0;
}

最后建议把以上代码复制到自己的编译器上,因为上面的字体看着好费劲(我是从我自己的编译器里写好了之后复制到这里的)

提示:此篇文章为博主原创文章,未经博主许可,不得转载或用于商业用途。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值