关于 Linklist 的深入理解
由于鄙人学习链表时太过于肤浅,
故作此篇来铭志!
刚开始学链表时,看各种代码,发现 malloc 函数使用频率特别高,
好奇,动不动就出现 Linklist 的创建,缺乏
对链表头结点的理解:
第一个结点的处理和其他结点是不同的,原因是第一个结点加入时链表为空,
它没有直接前驱结点,它的地址就是整个链表的指针,需要放在链表的头指针变量中;
而其它结点有直接的前驱结点,其地址放入直接前驱结点的指针域。
“第一个结点”的问题在很多操作中都会遇到,如在链表中插入结点时,将结点插在第一个位置和其他位置是不同的,
在链表中删除结点时,删除的第一个结点和其他结点的处理也是不同的,等等,
为了方便操作,有时在链表节点的头部插入一个“头结点”,头结点的类型与数据结点一致,
标识链表的头指针变量 L 中存放该结点的地址,这样即便是空表,头指针变量 head 也不为空。
另外,有些同学对于 typedef 不是很理解!
自行了解 抽象数据类型 !
或许会认为直接使用 int 不就好了?
typedef int datatype ;不显得多此一举吗?
的确,对于小项目而言,确实多此一举!
但是,倘若先前 定义 类型时,错误的定义成 char 型,
想要在整个代码中转换类型,显然是费时费力的,
typedef 就能很好的做到这一点!
还有一点不是很明确!
(Linklist)malloc(sizeof(Lnode));
书上的这个式子,malloc 前后随着题目的变化,到底应该放什么进去?
总不能死记硬背吧!
int *p; p = (int *)malloc(sizeof(int));
这个示例帮助理解下。
#include <bits/stdc++.h> using namespace std; //节点类模板 template <class ElemType> struct Node { ElemType data; Node<ElemType> *next; Node(); Node(const ElemType &e, Node<ElemType> *link = NULL); }; template <class ElemType> Node<ElemType>::Node() { next = NULL; } template <class ElemType> Node<ElemType>::Node(const ElemType &e, Node<ElemType> *link) { data = e; next = link; } template <class ElemType> class SimpleLinkList { protected: Node<ElemType> *head; Node<ElemType> *GetElemPtr(int position) const; public: SimpleLinkList(); virtual ~SimpleLinkList(); int Length() const; bool Empty() const; void Clear(); void Traverse(void (*visit)(const ElemType &)) const; bool GetElem(int position, ElemType &e) const; bool SetElem(int position, const ElemType &e); bool Delete(int posistion, ElemType &e); bool Delete(int position); bool Insert(int position, const ElemType &e); SimpleLinkList(const SimpleLinkList<ElemType> &source); SimpleLinkList<ElemType> &operator=(const SimpleLinkList<ElemType> &source); }; template<class ElemType> Node<ElemType> *SimpleLinkList<ElemType>::GetElemPtr(int position) const { Node<ElemType> *temPtr = head; int temPos = 0; while(temPtr != NULL && temPos < position) { temPtr=temPtr->next; temPos++; } if (temPtr != NULL && temPos == position) { return temPtr; } else { return NULL; } } template<class ElemType> SimpleLinkList<ElemType>::SimpleLinkList() { head = new Node<ElemType>; } template<class ElemType> SimpleLinkList<ElemType>::~SimpleLinkList() { Clear(); delete head; } template<class ElemType> int SimpleLinkList<ElemType>::Length() const { int count = 0; for (Node<ElemType> *temPtr = head->next; temPtr != NULL; temPtr = temPtr->next) { count++; } return count; } template<class ElemType> bool SimpleLinkList<ElemType>::Empty() const { return head->next == NULL; } template<class ElemType> void SimpleLinkList<ElemType>::Clear() { while(!Empty()) { Delete(1); } } template<class ElemType> void SimpleLinkList<ElemType>::Traverse(void (*visit)(const ElemType &)) const { for (Node<ElemType> *temPtr = head->next; temPtr != NULL;temPtr=temPtr->next) { (*visit)(temPtr->data); } } template<class ElemType> bool SimpleLinkList<ElemType>::GetElem(int position,ElemType &e) const { if(position<1||position>Length()) { return false; } else { Node<ElemType> *temPtr = GetElemPtr(position); e = temPtr->data; return true; } } template<class ElemType> bool SimpleLinkList<ElemType>::SetElem(int position,const ElemType &e) { if(position<1||position>Length()) { return false; } else { Node<ElemType> *temPtr = GetElemPtr(position); temPtr->data = e; return true; } } template<class ElemType> bool SimpleLinkList<ElemType>::Insert(int position,const ElemType &e) { if(position<1||position>Length()+1) { return false; } else { Node<ElemType> *temPtr = GetElemPtr(position - 1); Node<ElemType> *newPtr = new Node<ElemType>(e, temPtr->next); temPtr->next = newPtr; return true; } } template<class ElemType> bool SimpleLinkList<ElemType>::Delete(int position,ElemType &e) { if(position<1||position>Length()) { return false; } else { Node<template> *temPtr = GetElemPtr(position - 1); Node<ElemType> *nextPtr = temPtr->next; temPtr->next = nextPtr->next; e = nextPtr->data; delete nextPtr; return true; } }
本文来自博客园,作者:小白兔奶糖, 侵权必究!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?