C++学习笔记-数据结构-单链表的实现

这是学习C++的数据结构的第一个笔记,留着自己今后忘了的时候再看看吧

#include <iostream>

using namespace std;

// 定义一个打印回调指针,由使用者实现
typedef void(*PRINTLINKLIST)(void*);

// 链表节点
typedef struct LINKNODE
{
	void*	  data;			//指向链表上的数据
	struct LINKNODE* next;	//指向下一个节点
	LINKNODE() {
		data = nullptr;		//数据指向空
		next = nullptr;		//指向下一个空节点
	}
}LinkNode;

typedef struct LINKLIST
{
	LinkNode* head; //链表表头
	int		  size; //链表节点数目(除去头节点)
	LINKLIST() {
		head = nullptr;
		size = 0;
	}
}LinkList;

// 初始化链表
LinkList* initLinkList()
{
	LinkList* pList = new LinkList;
	// 创建一个头节点
	pList->head = new LinkNode;

	return pList;
}
//插入数据
bool insertNode(LinkList* pList, int pos, void* pData)
{
	if (nullptr == pList || nullptr == pData)
		return false;
	// 如果插入的位置大于链表节点数,那么就把节点插入到链表最后
	if (pList->size < pos)
		pos = pList->size;

	// 创建一个新的节点并存放数据
	LinkNode* pNewNode = new LinkNode;
	pNewNode->data = pData;

	// 循环找到指定节点位置的前一个位置
	LinkNode* pCurNode = pList->head;
	for (int i = 0; i < pos; ++i)
		pCurNode = pCurNode->next;

	// 让新的节点的下一个节点指向找到的节点的下一个节点
	pNewNode->next = pCurNode->next;
	// 再让找到的节点下一个节点指向新的节点
	pCurNode->next = pNewNode;

	//链表长度增加1
	pList->size++;

	return true;
}

int qureyNode(LinkList* pList, void *pData)
{
	int pos = 0;
	if (nullptr == pList || nullptr == pData || 0 == pList->size)
		return -1;

	// 拿到第一个数据节点
	LinkNode* pCurNode = pList->head->next;
	for (int i = 0; i < pList->size; ++i) 
	{
		// 如果是查询的数据就跳槽循环
		if (pData == pCurNode->data)
			break;
		// 否则就继续查找
		pCurNode = pCurNode->next;
		pos++;
	}
	return pos;
}

//反转链表
void reversalList(LinkList *pList)
{
	if (nullptr == pList || 0 == pList->size)
		return;

	// 当前第一个数据节点
	LinkNode* pCurNode = pList->head->next;
	// 当前节点的后继
	LinkNode* pPreNode = nullptr;
	// 当前节点的前驱	
	LinkNode* pSucNode = nullptr;

	// 可以理解为学生时期排队后向后转的场景
	while (pCurNode) 
	{
		// 先获取到当前节点的后继
		pPreNode = pCurNode->next;
		// 再把当前节点的后继改为当前节点的前驱(反转)
		pCurNode->next = pSucNode;
		// 反转后把后继指向当前节点(移动指针)
		pSucNode = pCurNode;
		// 移动完成后把当前节点改为当前节点的后继也就是pPreNode(移动指针)
		pCurNode = pPreNode;
		// 接下来就把当前指针的前驱改为当前指针的后继 也就是第一步(循环)
	}
	// 当循环到最后时,pCurNode与pPreNode都指向NULL,此时pCurNode的后继也就是原来最后一个节点
	// 目前就成为反转过后的第一个节点,所以就让表头指向pSucNode就完成转换了
	pList->head->next = pSucNode;
}

bool deleteNode(LinkList* pList, int pos)
{
	if (nullptr == pList || pos >= pList->size)
		return false;

	// 定位到删除节点的前一个节点
	LinkNode* pCurNode = pList->head;
	for (int i = 0; i < pos; ++i)
		pCurNode = pCurNode->next;
	// 待删除节点
	LinkNode *pDelNode = pCurNode->next;
	pCurNode->next = pDelNode->next;
	// 删除节点(这里只是删除链表节点 而不是真正的删除数据)
	delete pDelNode;
	pDelNode = nullptr;

	// 链表节点数减一
	pList->size--;

	return true;
}

void printLinkList(LinkList* pList, PRINTLINKLIST print)
{
	if (nullptr == pList)
		return;

	// 定位到删除节点
	LinkNode* pCurNode = pList->head->next;
	for (int i = 0; i < pList->size; ++i)
	{
		// 回调打印函数
		print(pCurNode->data);
		// 循环下一个节点
		pCurNode = pCurNode->next;
	}
}

struct Student
{
	char name[64];
	int age;
	int code;
};

void myPrint(void *data)
{
	Student* p = (Student*)data;
	cout << "Name:" << p->name << " age:" << p->age << " code:" << p->code << endl;
}

int main()
{

	Student st1, st2, st3, st4, st5;
	st1 = { "A", 15, 96 };
	st2 = { "B", 16, 82 };
	st3 = { "C", 18, 55 };
	st4 = { "D", 17, 69 };
	st5 = { "E", 19, 89 };

	// 创建链表
	LinkList* pList = initLinkList();

	insertNode(pList, 0, &st1);
	insertNode(pList, 1, &st2);
	insertNode(pList, 2, &st3);
	insertNode(pList, 3, &st4);
	insertNode(pList, 4, &st5);
	// 打印
	printLinkList(pList, myPrint);
	cout << "========================" << endl;

	// 反转链表
	reversalList(pList);
	printLinkList(pList, myPrint);

	int pos = qureyNode(pList, &st3);
	if (-1 != pos) {
		deleteNode(pList, pos);
		cout << "=====成功删除节点:" << pos + 1 << "=====" << endl;
	}		
	printLinkList(pList, myPrint);
	

	system("pause");

	return 0;
}

运行结果:

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值