zoukankan      html  css  js  c++  java
  • 单链表

    线性链表

    线性链表的定义

    用一组任意的存储单元(可以连续,也可以不连续)存储线性表的数据元素。存储的数据只是逻辑上的相邻,不一定要求物理上的相邻。每一个存储的数据元素称为节点,一个节点包括两个域:其中存储数据元素的叫数据域;存储直接后继存储位置的域称为指针域。指针域中存储的信息称作指针。n个结点链接称为一个链表,也就是线性表


    易混淆概念

    1. 首元结点:链表中存储第一个数据元素的结点。
    2. 头结点:在首元结点之前附加的一个结点,其指针指向首元结点。
    3. 头指针:指向链表中第一个结点的指针。若有头结点,则指向头结点;若没有,直接指向首元结点。

    头结点的作用

    1. 便于首元结点的处理
      增加了头结点,就可以直接通过保存在头结点中的指针来对首元结点进行操作(就像其他元素一样),无需进行特殊处理。
    2. 便于空表和非空表的统一处理
      无论链表是否为空,头指针都是指向头结点的非空指针。要判定链表是否为空,只需要判断头结点的指针域是否为空就可以。

    基本操作的思路

    • 初始化
    1. 生成新节点作为头结点,用头指针L指向头结点。
    2. 头结点的指针域置空。
    • 向前插入元素
    1. 生成一个新结点*s
    2. 输入元素值赋给新结点*s的数据域
    3. 将新结点*s插入到头结点之后
    • 向后插入元素
    1. 生成一个新结点*s
    2. 输入元素值赋给新结点*的数据域
    3. 初始化一个定位指针*p,遍历后指向尾结点
    4. 将新结点*p插入到尾结点之后
    • 在中间插入元素(前插)
    1. 生成一个新结点*s
    2. 输入元素值赋给新结点*s的数据域
    3. 查找结点ai-1并将指针p指向结点ai
    4. 将结点*s的指针用户指向结点ai
    5. 将结点*p的指针域指向新结点*s
    • 删除某元素
    1. 让定位指针p指向结点ai-1
    2. 新建指针临时保存待删除结点ai的地址,以备释放
    3. 将结点*p的指针域指向ai+1
    4. 释放结点ai的空间

    基本操作的具体实现

    SingleLinkList.h

    #pragma once
    #define status bool
    #define OK true
    #define ERROR false
    #define YES true
    #define NO false
    
    template<typename DType>
    class Node {
    public :
            DType data;
            Node * next;
    };
    
    
    template<typename DType>
    class CSingleLinkList {
    private:
            Node<DType> *phead;   //链表头指针
            Node<DType> *head;    //头结点
    public:
            CSingleLinkList();   //构造函数
            ~CSingleLinkList();
    public:
            //初始化链表
        status InitSList();
            //获取链表长度
            int GetLength();
            //前插结点
            status FrontInsert(DType data);
            //后插结点
            status BackInsert(DType data);
            //在指定位置向前插入结点
            status InsertByOrder(int order, DType);
           //获取指定序号的元素值
            status GetElemByOrder(int order, DType &receiver);
            //查找指定元素的地址,找不到就返回空地址
            Node<DType>* GetLocByElem(DType target);
            //删除指定序号的结点
            status DelByOrder(int order);
            //打印链表
            void PrintList();
    
    };
    

    CSingelLinkList.cpp

    #include<iostream>
    #include"SingleLinkList.h"
    using namespace std;
    
    
    template<typename DType>
    CSingleLinkList<DType>::CSingleLinkList() {
            cout << "链表创建成功" << endl;
            InitSList();
    }
    
    //初始化链表
    template<typename DType>
    status CSingleLinkList<DType>::InitSList() {
            head = new Node<DType>;
            if (head != NULL) {
                   head->next = NULL;
                   phead = head;
                   return OK;
            }
            return  ERROR;
    }
    
    
    //获取链表长度
    template<typename DType>
    int CSingleLinkList<DType>::GetLength() {
            //新建追踪指针指向头结点
            Node<DType> *pTrack = this->head;    //直接用head也可以
    
            //记录长度
            int length = 0;
            //遍历链表开始计数
            /*if (!head->pnext) {
                   cout << "head->pnext is null" << endl;
            }*/
            while (pTrack->next!= NULL) {
                   //cout << pTrack->next;
                   pTrack = pTrack->next;
                   length++;
            }
            //cout << length;
            return length;
    }
    
    
    
    //前插入结点
    template<typename DType>
    status CSingleLinkList<DType>::FrontInsert(DType data) {
            //新建结点
            Node<DType> *p = new Node<DType>;
            //录入数据
            p->data = data;
            //令其指向头结点后一个
            p->next = head->next;
            //让头结点指向它
            head->next = p;
            return OK;
    }
    
    
    
    //后插结点
    template<typename DType>
    status CSingleLinkList<DType>::BackInsert(DType data) {
            //新建结点保存数据
            Node<DType> *p = new Node<DType>;
            p->data = data;
            //跟踪指针,指向头结点
            Node<DType> *pTrack = head;
            //遍历让其指向表尾
            while (pTrack->next != NULL) {
                   pTrack = pTrack->next;
            }
            pTrack->next = p;
            p->next = NULL;
            return OK;
    }
    
    
    
    //在指定位置向前插入结点
    template<typename DType>
    status CSingleLinkList<DType>::InsertByOrder(int order, DType data) {
            if (order<1 || order>this->GetLength()) {
                   return ERROR;
            }
            Node<DType>* pTrack = head;
            Node<DType>* q = new Node<DType>;
            q->data = data;
            int count = 0;
            //遍历到前驱结点
            while (count < order-1) {
                   pTrack = pTrack->next;
                   count++;
            }
            q->next = pTrack->next;
            pTrack->next = q;
            return OK;
    }
    
    
    
    //返回指定序号的元素值
    template<typename DType>
    status CSingleLinkList<DType>::GetElemByOrder(int order, DType &receiver) {
            int count = 0;  //记数器
            //获取数据用的指针
            Node<DType> *pGet = head;
            if (order<1 || order>this->GetLength()) {
                   return ERROR;
            }
            while (count != order) {
                   pGet = pGet->next;
                   count++;
            }
            receiver = pGet->data;
            return OK;
    }
    
    
    
    //查找指定元素的地址(返回首个符合的)
    template<typename DType>
    Node<DType>* CSingleLinkList<DType>::GetLocByElem(DType target) {
            //跟踪指针
            Node<DType> *pTrack = head;
            while(pTrack!=NULL) {
                   if (pTrack->data == target) {
                           return pTrack;
                   }
                   pTrack = pTrack->next;
            }
            return NULL;
    }
    
    
    
    //删除指定序号的结点
    template<typename DType>
    status CSingleLinkList<DType>::DelByOrder(int order) {
            int count = 0;
            Node<DType>* pTrack = head;
            if (order<1 || order>this->GetLength()) {
                   return ERROR;
            }
            //找到被删除结点的前驱节点
            while (count < order-1) {
                   pTrack = pTrack->next;
                   count++;
            }
            //保存被删除节点,方便删除
            Node<DType>* tmp = pTrack->next;  
            //让前驱节点指向后驱结点
            pTrack->next = tmp->next;
            //释放被删除结点
            delete tmp;
            return OK;
    }
    
    
    
    //打印链表
    template<typename DType>
    void CSingleLinkList<DType>::PrintList() {
            if (this->GetLength() == 0) {
                   cout << "链表为空!" << endl;
            }
           //指向首元结点,头结点不保存数据
           Node<DType>* pTrack = head->next;
            cout << "================打印链表===============" << endl;
           while (pTrack!=NULL) {
                   cout << pTrack->data << " ";
                   pTrack = pTrack->next;
            }
            cout << endl;
    }
    
    
    
  • 相关阅读:
    C#学习笔记(委托)
    C#学习笔记(函数——如何在函数中传入传出参数)
    C#学习笔记(隐式和显式转化、枚举类型、结构类型、数组类型和字符串)
    C#学习笔记(流程语句)
    C#学习笔记(基本语法)
    java调用exe,及调用bat不成功的解决办法
    JS数组去重精简版
    根据经纬度坐标获取位置信息(基于百度地图)
    图解算法习题之老王的杂货铺
    JS中的MOD运算
  • 原文地址:https://www.cnblogs.com/urahyou/p/11408649.html
Copyright © 2011-2022 走看看