线性表--单链表(C++)

单链表演示图:

单链表结构体:

struct Node
{
	Node(const DataType& d)//节点的构造函数
	:_data(d)
	,_next(NULL)
	{}
	DataType _data;        //数据  
	struct Node *_next;    //指向下一个节点的指针
};

带头结点和尾节点的单链表:

多一个Tail指针的好处就是很方便可以找到链表尾部,方便在尾部插入一个元素什么的。

下面我们用类来实现单链表:

class SList
{
	friend ostream& operator<<(ostream& os, const SList& s);  //输出运算符重载(友元)
public:
	SList()                           //构造函数
		:_head(NULL)
		,_tail(NULL)
	{}
	SList(const SList& s)             //拷贝构造
		:_head(NULL)
		, _tail(NULL)
	{
		Node *cur = _head;
		while (cur)
		{
			PushBack(cur->_data );
			cur = cur->_next;
		}
		_tail = cur;
	}
	~SList()                           //析构函数
	{
		if (_head == NULL)
			return;
		Node *cur = _head;
		if (cur != NULL)
		{
			Node *del = cur;
			cur = cur->_next;
			delete del;
		}
		_tail = NULL;
		_head = NULL;
	}

	SList& operator=(SList s)           //赋值运算符重载
	{
		swap(_head, s._head);
		swap(_tail, s._tail);
		return *this;
	}

单链表最基本的四个函数:

void SList::PushBack(const DataType& d)   //尾插
{
	Node *newNode = new Node(d);      //构建一个新的节点
	if (_head == NULL)
	{
		_head = newNode;
		_tail = newNode;
	}
	else
	{
		_tail->_next = newNode;
		_tail = newNode;
	}
}
void SList::PushFront(const DataType& d)   //头插
{
	Node *newNode = new Node(d);
	if (_head == NULL)
	{
		_head = newNode;
		_tail = newNode;
	}
	else
	{
		newNode->_next = _head;
		_head = newNode;
	}
}
void SList::PopBack()                     //尾删
{
	if (_head == NULL)
		return;
	else if (_head == _tail)
	{
		delete _tail;
		_tail = NULL;
		_head = NULL;
	}
	else
	{
		Node *cur = _head;
		while (cur->_next != _tail)
		{
			cur = cur->_next;
		}
		delete _tail;
		_tail = cur;
		_tail->_next = NULL;
	}
}
void SList::PopFront()                  //头删
{
	if (_head == NULL)
		return;
	else if (_head == _tail)
	{
		delete _tail;
		_tail = NULL;
		_head = NULL;
	}
	else
	{
		Node *del = _head;
		_head = _head->_next;
		delete del;
	}
}

给一个数据,若找到该节点则返回该节点,没找到则返回NULL

Node* SList::Find(const DataType& d)
{
	Node *cur = _head;
	while (cur != NULL)
	{
		if (cur->_data == d)
			return cur;
		cur = cur->_next;
	}
	return NULL;
}

给定一个节点,在该节点后插入一个新的节点

void SList::Insert(Node* pos, const DataType& d)
{
	Node *newNode = new Node(d);
	if (pos == _tail)                    //若给定的节点是尾节点,此处可以直接调用尾插
	{
		_tail->_next = newNode;
		_tail = newNode;
	}
	else
	{
		newNode->_next = pos->_next;
		pos->_next = newNode;
	}
}

链表的逆序:此处用三个指针来实现

void SList::Reverse()
{
	Node *p1 = NULL;
	Node *p2 = _head;
	Node *newhead = NULL;
	while (p2)
	{
		p1 = p2;
		p2 = p2->_next;
		p1->_next = newhead;
		newhead = p1;

	}
	_head = newhead;
}

链表的排序:采用冒泡排序

void SList::Sort()
{
	Node *cur = _head;
	Node *end = NULL;
	while (cur != end)
	{
		while (cur->_next  != end)
		{
			if (cur->_data > cur->_next->_data)
			{
				DataType tmp = cur->_data;
				cur->_data = cur->_next->_data;
				cur->_next->_data = tmp;
			}
          cur = cur->_next;
		}
	  end = cur;
      cur = _head;
	}
}

删除某个节点(给定一个数据,删除数据与之相等的第一个节点)

void SList::Remove(const DataType& d)
{
	Node *cur = _head;
	while (cur != NULL)
	{
		if (cur->_data == d)
		{
			Node *del = cur->_next;
			DataType tmp = cur->_data;
			cur->_data = cur->_next->_data;
			cur->_next->_data = tmp;
			cur->_next = cur->_next->_next;
			delete del;
			return;
		}
		cur = cur->_next;
	}
}

删除某些节点(给定一个数据,删除数据与之相等的每一个节点)

void SList::RemoveAll(const DataType& d)
{
	Node *cur = _head;
	while (cur != NULL)
	{
		if (cur->_data == d)
		{
			Node *del = cur->_next;
			DataType tmp = cur->_data;
			cur->_data = cur->_next->_data;
			cur->_next->_data = tmp;
			cur->_next = cur->_next->_next;
			delete del;
		}
		cur = cur->_next;
	}
	return;
}

删除非尾节点

void SList::EarseNotTail(Node *pos)
{
	Node *del = pos;
	Node *cur = _head;
	while (cur->_next!=pos)     //找到该节点的前一个节点
	{
		cur = cur->_next;
	}
	cur->_next = pos->_next;     //让它的_next指向要删除节点的_next
	delete del;
}

找到中间节点

Node*  SList::FindMinNode()                //快慢指针问题
{                                          //两个指针都指向头结点
	Node *cur = _head;                 //快的一次走两步,慢的一次走一步
	Node *fast = cur;                  //当快指针走到尾的时候,慢指针指向中间节点
	Node *slow = cur;
	while (fast)
	{
		fast = fast->_next->_next;
		slow = slow->_next;
	}
	return slow;
}

删除倒数第K个节点

void  SList::DelKNode(int k)
{
	Node *cur = _head;
	int i = k - 1;
	while (i)                   //先让cur指向正数第K个节点
	{
		cur = cur->_next;
		i = i - 1;;
	}
	Node *p1 = _head;            
	Node *tmp = NULL;
	while (cur->_next )          //让一个指向头结点的指针和cur一起走
	{
		tmp = p1;
		p1 = p1->_next;
		cur = cur->_next;     //当cur指向尾节点时,那个指针指向倒第K个节点
	}
	Node *del = p1;
	tmp->_next = p1->_next ;
	delete p1;

}

检测是否带环

//检测是否带环
int  SList::CheckCycle(const SList& s)      //快慢指针问题
{
	Node *fast = _head;
	Node *slow = _head;
	while (slow)
	{
		if (slow == fast)
		{
			return 1;
		}
		fast = fast->_next->_next;
		slow = slow->_next;
	}
	return 0;
}

获取环的入口点

Node*  SList::GetCycleEoryNode()
{
	Node *cur = _head;
	while (cur)
	{
		if (cur == _tail)
		{
			return cur;
		}
		cur = cur->_next;
	}
	return NULL;
}

判断是否相交

int  SList::CheckCross(SList& l1, SList& l2)
{
	int count1 = l1.LengthOfList(l1);
	int count2 = l2.LengthOfList(l2);
	if (count1 > count2)
	{
		Node *cur = l1._head;
		while (cur)
		{
			if (l2._tail == cur)
				return 1;
			cur = cur->_next;
		}
	}
	else
	{
		Node *cur = l2._head;
		while (cur)
		{
			if (l1._tail == cur)
				return 1;
			cur = cur->_next;
		}
	}
	return 0;
}

合并两个链表

int  SList::CheckCross(SList& l1, SList& l2)
{
	int count1 = l1.LengthOfList(l1);
	int count2 = l2.LengthOfList(l2);
	if (count1 > count2)
	{
		Node *cur = l1._head;
		while (cur)
		{
			if (l2._tail == cur)
				return 1;
			cur = cur->_next;
		}
	}
	else
	{
		Node *cur = l2._head;
		while (cur)
		{
			if (l1._tail == cur)
				return 1;
			cur = cur->_next;
		}
	}
	return 0;
}

求两个链表的交点

Node*  SList::GetLinkCross(SList& l1, SList& l2)
{ 
	int count1 = l1.LengthOfList(l1);
	int count2 = l2.LengthOfList(l2);
	Node *cur1 = l1._head;
	Node *cur2 = l2._head;
	if (count1 > count2)
	{
		Node *cur1 = l1._head;
		Node *cur2 = l2._head;
		while (cur2)
		{
			if (cur2->_next  == cur1->_next )
				return cur1;
			else
			{
				cur1 = cur1->_next;
				cur2 = cur2->_next;
			}
		}
	}
	else
	{
		Node *cur1 = l1._head;
		Node *cur2 = l2._head;
		while (cur1)
		{
			if (cur2->_next == cur1->_next)
				return cur1;
			else
			{
				cur1 = cur1->_next;
				cur2 = cur2->_next;
			}
		}
	}
	return NULL;
}

求链表长度

int SList::LengthOfList(const SList& s)

{

int length = 0;

Node *cur = _head;

while (cur)

{

length++;

cur = cur->_next;

}

return length;

}

以后会有改进版奉上,希望大家多多支持

时间: 2024-08-02 02:50:12

线性表--单链表(C++)的相关文章

JAVA实现具有迭代器的线性表(单链表)

一,迭代器的基本知识: 1,为什么要用迭代器?(迭代:即对每一个元素进行一次“问候”) 比如说,我们定义了一个ADT(抽象数据类型),作为ADT的一种实现,如单链表.而单链表的基本操作中,大部分需要用到依次遍历单链表中的每一个元素.一般而言,我们就是用for循环来实现遍历,这样,当你新增一个对单链表的操作并需要使用遍历时,你就得重新写一个for循环而实现遍历.那么,为什么不将迭代(遍历)作为一种基本的ADT操作(基本的ADT操作如:新增一个元素.删除一个元素)呢?于是,迭代器就出场了. 2,鉴于

线性表—单链表

.1.链式存储结构实现 单链表和双链表(这边讲单链表). 2.基础概念 a.结点:结点由数据域和地址域(链)两部分组成.而结点整体在效果上可以看作是该结点的地址(指针).这个地址域一般是后继元素的地址(即下一个结点的总体).所以最后一个元素的地址域为^,其表示空,即没有后续元素.b.单链表:每个结点只有一个地址域的线性链表称为单链表.c.双链表:每个结点有两个地址域的线性表链称为双链表,两个地址域分别指向前驱元素和后继元素. 3.单链表的实现 线性表接口LList: package com.cl

Python线性表——单链表

1. 线性表简介 线性表是一种线性结构,它是由零个或多个数据元素构成的有限序列.线性表的特征是在一个序列中,除了头尾元素,每个元素都有且只有一个直接前驱,有且只有一个直接后继,而序列头元素没有直接前驱,序列尾元素没有直接后继. 数据结构中常见的线性结构有数组.单链表.双链表.循环链表等.线性表中的元素为某种相同的抽象数据类型.可以是C语言的内置类型或结构体,也可以是C++自定义类型. 2. 数组 数组在实际的物理内存上也是连续存储的,数组有上界和下界.C语言中定义一个数组: 数组下标是从0开始的

【 数据结构(C语言)】线性表——单链表

1.线性链表:用任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的也可以是不连续) #include <bits/stdc++.h> using namespace std; #define ElemType int #define Status int #define ERROR -1 #define OK 1 typedef struct LNode { ElemType data; struct LNode *next; }LNode ,*LinkList; LinkList

数据结构之 线性表---单链表的拆分

数据结构实验之链表五:单链表的拆分 Time Limit: 1000MS Memory limit: 65536K 题目描述 输入N个整数顺序建立一个单链表,将该单链表拆分成两个子链表,第一个子链表存放了所有的偶数,第二个子链表存放了所有的奇数.两个子链表中数据的相对次序与原链表一致. 输入 第一行输入整数N;: 第二行依次输入N个整数. 输出 第一行分别输出偶数链表与奇数链表的元素个数: 第二行依次输出偶数子链表的所有数据: 第三行依次输出奇数子链表的所有数据. 示例输入 10 1 3 22

数据结构之 线性表---单链表操作A (删除链表中的指定元素)

数据结构上机测试2-1:单链表操作A Time Limit: 1000MS Memory limit: 4096K 题目描述 输入n个整数,先按照数据输入的顺序建立一个带头结点的单链表,再输入一个数据m,将单链表中的值为m的结点全部删除.分别输出建立的初始单链表和完成删除后的单链表. 输入 第一行输入数据个数n: 第二行依次输入n个整数: 第三行输入欲删除数据m. 输出 第一行输出原始单链表的长度: 第二行依次输出原始单链表的数据: 第三行输出完成删除后的单链表长度: 第四行依次输出完成删除后的

数据结构 线性表—单链表

本文只要实现单链表的初始化.插入(尾插.头插.任意位置插入).删除(尾删.头删.删除指定元素).查找等. 定义单链表 typedef int DataType; typedef struct LinkNode {  DataType data;  struct LinkNode *next; }LinkNode, *pLinkNode, *pList; 实现单链表的所有接口: void InitLinkList(pList* pHead);//单链表的初始化 void Destroy(pList

数据结构之 线性表---单链表的操作B(先逆序+再删除重复元素)

数据结构上机测试2-2:单链表操作B Time Limit: 1000MS Memory limit: 65536K 题目描述 按照数据输入的相反顺序(逆位序)建立一个单链表,并将单链表中重复的元素删除(值相同的元素只保留最后输入的一个). 输入 第一行输入元素个数n: 第二行输入n个整数. 输出 第一行输出初始链表元素个数: 第二行输出按照逆位序所建立的初始链表: 第三行输出删除重复元素后的单链表元素个数: 第四行输出删除重复元素后的单链表. 示例输入 10 21 30 14 55 32 63

数据结构(一)线性表单链表试题

题目 快速找到未知长度的单链表的中间节点 解决思路 (一)使用一个指针,先索引一遍获取总长度,再取长度一半去循环获取到中间值 算法复杂度:O(L)+O(L/2) = O(3L/2) (二)使用两个指针,快指针和慢指针,快指针一次向前走2格,慢指针一次走一格,当快指针走完全程,慢指针正好走在中间 算法复杂度:O(L/2) 方法二:代码实现 //快速查找中间元素 int FindMidEle(LinkList L, Elemtype *e) { LinkList search, middle; //