线性链表的实现

一、实现

CList作为一个链表类,它的成员是由CNode组成。

CNode有两个属性,tElement用于指向当前的节点,next用于指向下一个节点

定义List.h文件

#pragma once
#ifndef _List_
#define  _List_

#include <Windows.h>

//链表节点
template<typename T>
class CNode
{
public:
	CNode(T* tElement) :tElement(tElement), next(0) {}
	T* Element() const { return tElement; }
	CNode*& Next() { return next; }

private:
	T* tElement;//用于指示当前节点
	CNode* next;//用于指示下一个节点
};


template <typename T>
class CList
{
public:
	CList() : dwCount(0), head(0) { }
	CList(T* tElement) : dwCount(1), head(new CNode<T>(tElement)) { }
	virtual ~CList() { }
public:
	void Append(CNode<T>*& node, T* tElement);//添加
	void Insert(T* tElement);//插入
	bool Remove(T* tElement);//删除
	DWORD Count() const { return dwCount; }//节点数量
	CNode<T>*& Head() { return head; }//节点头
	T* GetFirst() { return head != NULL ? head->Element() : NULL; }
	T* GetLast();
	T* GetNext(T* tElement);
	T* Find(DWORD(*Function)(T* tParameter), DWORD dwValue);

protected:
	CList(const CList& list);//防止默认拷贝发生
	CList& operator = (const CList& list);
private:
	CNode<T>* head;
	DWORD dwCount;
};

#endif // _List_

定义CList.cpp

#include "CList.h"

template<typename T>
void CList<T>::Append(CNode<T>*& node, T* tElement)
{
	if (node == NULL)
	{
		dwCount++;
		node = new CNode<T>(tElement);
		return;
	}

	Append(node->Next(), tElement);
}

template<typename T>
void CList<T>::Insert(T * tElement)
{
	dwCount++;
	if (head == NULL)
	{
		head = new CNode<T>(tElement);
		return;
	}

	CNode<T>* tmp = head;
	head = new CNode<T>(tElement);
	head->Next() = tmp;
}

template<typename T>
bool CList<T>::Remove(T * tElement)
{
	if (head == NULL)
	{
		return NULL;
	}

	if (head->Element() == tElement)
	{
		CNode<T>* tmp = head;
		head = head->Next();

		delete tmp;
		dwCount--;

		return true;
	}

	CNode<T>* tmp = head;
	CNode<T>* lst = head->Next();

	while (lst != NULL)
	{
		if (lst->Element() == tElement)
		{
			tmp->Next() = lst->Next();

			delete lst;
			dwCount--;

			return true;
		}

		lst = lst->Next();
		tmp = tmp->Next();
	}

	return false;
}

template<typename T>
T * CList<T>::GetLast()
{
	if (head)
	{
		CNode<T>* tmp = head;
		while (tmp->Next())
		{
			tmp = tmp->Next();
		}
		return tmp->Element();
	}

	return NULL;
}

template<typename T>
T * CList<T>::GetNext(T * tElement)
{
	if (head == NULL)
	{
		return NULL;
	}

	if (tElement == NULL)
	{
		return GetFirst();
	}

	if (head->Element() == tElement)
	{
		return head->Next() != NULL ? head->Next()->Element() : NULL;
	}

	CNode<T>* lst = head->Next();

	while (lst != NULL)
	{
		if (lst->Element() == tElement)
		{
			return lst->Next() != NULL ? lst->Next()->Element() : NULL;
		}

		lst = lst->Next();
	}

	return NULL;
}

template<typename T>
T * CList<T>::Find(DWORD(*Function)(T *tParameter), DWORD dwValue)
{
	try
	{
		T* tElement = NULL;
		while (tElement = GetNext(tElement))
		{
			if (Function(tElement) == dwValue)
			{
				return tElement;
			}
		}
	}
	catch (...) {}

	return NULL;
}

template <typename T>
CList<T>::CList(const CList& list)
{
	head = new CList<T>;
	memcpy(head, list.head, CList<T>);
	dwCount = list.dwCount;
}

template <typename T>
CList<T>& CList<T>::operator= (const CList& list)
{
	dwCount = list.dwCount;
	CList<T>* temp = new CList<T>;
	memcpy(temp, list.head, CList<T>);

	delete[]head;
	head = temp;
	return *this;
}






二、注释

首先,解释一下CList类。为了更方便地处理,该链表由CNode类型的元素组成。CNode类有两个特征:tElement指针(指向用户自定义的元素)和next指针(指向链表下一个项);实现了两个方法:ElementNextElement方法返回当前元素地址的指针,Next方法返回下一个项地址的引用。

Find方法显然是一个高级特性,针对未定义类型T和未定义的Function方法(带tParameter参数)设计。假设要使用一个包含学生对象的链表,例如迭代数据(如,使用GetNext方法)或查找某个学生。如果有可能为将来定义的类型实现一个返回unsigned long类型(DWORD)的方法,而且该方法要把未知类型数据与dwValue参数做比较,应该怎么做?例如,假设要根据学生的ID找出这名学生,可以使用下面的代码:

#include <windows.h>
#include "CList.h"

class CStudent
{
public:
  CStudent(DWORD dwStudentId) : dwStudentId(dwStudentId){ }
  static DWORD GetStudentId(CStudent* student)
  {
    DWORD dwValue = student->GetId();
    return dwValue;
  }
  DWORD GetId() const
  {
    return dwStudentId;
  }
private:
  DWORD dwStudentId;
};

int main()
{
  CList<CStudent>* list = new CList<CStudent>();
  list->Insert(new CStudent(1));
  list->Insert(new CStudent(2));
  list->Insert(new CStudent(3));
  CStudent* s = list->Find(&CStudent::GetStudentId, 2);
  if (s != NULL)
  {
    // 找到s
  }
  return 0;
}```

 

参考:

https://yq.aliyun.com/articles/92420/

https://blog.csdn.net/qq_33373173/article/details/86564959

https://blog.csdn.net/lwbeyond/article/details/6202256

https://blog.csdn.net/zhuiqiuzhuoyue583/article/details/80450843

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值