B站头图景深对焦效果

请在图片上左右移动鼠标查看效果

关于 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;
    }
}
复制代码

 

posted @   acmWang  阅读(259)  评论(0编辑  收藏  举报
编辑推荐:
· 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爆火,是硬核还是营销?
返回顶端

2021-09-22 (星期三)
09:08:39 +08:00

点击右上角即可分享
微信分享提示