zoukankan      html  css  js  c++  java
  • 数据结构学习记录连载3(链表的学习)

    基本要求:

    1) 用模板方法建立链表的结点类ListNode和单链表类LinList,编写程序实现向单链表插入100整数,然后,以插入次序删除这100个整数。

    提高要求:

    1) 简单修改程序,将单链表类LinList改为双向循环链表类。向双向循环链表插入100字符,然后,以插入次序删除这100个字符。

    2) 编写函数实现单链表类LinList的对象B连接到单链表类LinList的对象A的尾部:Void Concatenate(LinList& A, LinList& B)。

    1.ListNode.h结点定义:

    /*
    * Copyright (c) 2009,FreshAir团队嵌入式软件研发组
    * All rights reserved.
    *
    * 文件名称:ListNode.h
    * 摘 要: 节点类的定义
    *
    * 当前版本:1.0
    * 作 者: 吴友强
    * 完成日期:2009年10月13日
    *
    * 取代版本:
    * 原作者 :
    * 完成日期:
    */

    #include<iostream.h>
    #include<stdio.h>

    template<class T> class LinkList; //前视定义,否则,无法定义友元
    template<class T> class ListNode
    {
     friend class LinkList<T>;  //定义友元
    private:
     ListNode<T> *next;    //指向下一个结点的指针
    public:
     T data;
     ListNode(ListNode<T> *ptrNext = NULL); //构造函数,用于构造头结点
     ListNode(const T& item, ListNode<T> *ptrNext = NULL);//构造函数,非头结点
     ~ListNode() {};     //析构函数
     friend void Concatenate(LinkList<T>& target, LinkList<T>& souce);
    };

    template<class T>
    ListNode<T>::ListNode(ListNode<T> *ptrNext):next(ptrNext)
    {
     
    }

    template<class T>
    ListNode<T>::ListNode(const T &item, ListNode<T> *ptrNext)
    {
     data = item;
     next = ptrNext;
    }

    2.LinkList.h定义单链表类及实现:

    /*
    * Copyright (c) 2009,FreshAir团队嵌入式软件研发组
    * All rights reserved.
    *
    * 文件名称:LinkList.h
    * 摘 要: 单链表类的定义
    *
    * 当前版本:1.0
    * 作 者: 吴友强
    * 完成日期:2009年10月13日
    *
    * 取代版本:
    * 原作者 :
    * 完成日期:
    */

    #include "ListNode.h"

    template <class T>
    class LinkList
    {
    private:
     ListNode<T> *head;      //指向头结点的指针
     int size;        //单链表的元素个数
     ListNode<T> *currPtr;     //当前结点
    public:
     LinkList(void);       //构造函数
     ~LinkList();      //析构函数

     //线性表操作要求的成员函数
     int GetListSize(void) const;   //返回链表的元素个数
     int ListIsEmpty(void) const;   //判断单链表是否为空
     ListNode<T> *Index(int pos);   //定位
     void Insert(const T& item, int pos); //插入
     T Delete(int pos);      //删除
     T GetData(int pos);      //取元素
     void ClearList(void);     //清空链表

     //遍历单链表的成员函数
     ListNode<T> *Reset(int pos=0);   //把第pos个结点设置为当前结点currPtr
     ListNode<T> *Next(void);    //currPtr指向下一个结点
     int EndOfList(void) const;    //currPtr是否指在链表尾

     friend void Concatenate(LinkList<T>& target, LinkList<T>& souce);
    }; 

     

    /*
    * Copyright (c) 2009,FreshAir团队嵌入式软件研发组
    * All rights reserved.
    *
    * 文件名称:LinkList.cpp
    * 摘 要: 单链表的各个功能函数的现实
    *
    * 当前版本:1.0
    * 作 者: 吴友强
    * 完成日期:2009年10月13日
    *
    * 取代版本:
    * 原作者 :
    * 完成日期:
    */

    template <class T>
    LinkList<T>::LinkList(void) 
    {
     size = 0;
     head = new ListNode<T>();
    }

    template <class T>
    LinkList<T>::~LinkList()
    {
     ClearList(); //释放所有非头结点的结点
     delete head; //释放头结点
    }

    /*
    * 函数名称: GetListSize
    * 输 入:
    * 输 出:
    * 功能描述: 返回顺序表的元素个数size
    * 作 者: 吴友强
    * 日 期: 2009年10月13日
    * 修 改:
    * 日 期:
    */
    template <class T>
    int LinkList<T>::GetListSize(void) const 
    {
     return size;
    }

    /*
    * 函数名称: ListIsEmpty
    * 输 入:
    * 输 出:
    * 功能描述: 判断是否为空,空返回1;非返回0
    * 作 者: 吴友强
    * 日 期: 2009年10月13日
    * 修 改:
    * 日 期:
    */
    template <class T>
    int LinkList<T>::ListIsEmpty(void) const
    {
     return size == 0 ? 1 : 0;
    }

    /*
    * 函数名称: Index
    * 输 入: pos
    * pos: 定位数据元素结点
    * 输 出:
    * 功能描述: 定位至第pos个数据元素结点,返回指向第pos个结点的指针
    * 作 者: 吴友强
    * 日 期: 2009年10月13日
    * 修 改:
    * 日 期:
    */
    template <class T>
    ListNode<T> *LinkList<T>::Index(int pos)
    {
     if (pos < -1 || pos > size)
     {
      cout << "参数pos越界出错!" << endl;
      exit(0);
     }

     if (pos == -1)
     {
      return head;
     }

     ListNode<T> *p = head->next;
     int i = 0;
     while (p != NULL && i <pos)
     {
      p = p->next;
      i++;
     }

     return p;
    }

    /*
    * 函数名称: Insert
    * 输 入: pos
    * pos: 插入数据元素结点的位置
    * item: 插入数据结点的数据
    * 输 出:
    * 功能描述: 在pos个结点之前插入一个data域为item的新结点
    * 作 者: 吴友强
    * 日 期: 2009年10月13日
    * 修 改:
    * 日 期:
    */
    template <class T>
    void LinkList<T>::Insert(const T& item, int pos)
    {
     if (pos < 0 || pos > size)
     {
      cout << "参数pos越界出错!" << endl;
      exit(0);
     }

     ListNode<T> *p = Index(pos - 1);
     ListNode<T> *newNode = new ListNode<T>(item, p->next);
     p->next = newNode;
     size++;
    }

    /*
    * 函数名称: Delete
    * 输 入: pos
    * pos: 删除数据元素结点的位置
    * 输 出:
    * 功能描述: 删除第pos个结点,并返回被删除结点的data
    * 作 者: 吴友强
    * 日 期: 2009年10月13日
    * 修 改:
    * 日 期:
    */
    template <class T>
    T LinkList<T>::Delete(int pos)
    {
     T temp;
     if (pos < 0 || pos > size-1)
     {
      cout << "参数pos越界出错!" << endl;
      exit(0);
     }

     ListNode<T> *q, *p = Index(pos - 1);
     q = p->next;
     p->next = p->next->next;
     temp = q->data;
     delete q;
     size--;

     return temp;
    }

    /*
    * 函数名称: ClearList
    * 输 入: pos
    * pos: 删除数据元素结点的位置
    * 输 出:
    * 功能描述: 清空表为初始化状态
    * 作 者: 吴友强
    * 日 期: 2009年10月13日
    * 修 改:
    * 日 期:
    */
    template <class T>
    void LinkList<T>::ClearList(void)
    {
     ListNode<T> *p = head->next;
     ListNode<T> *q;

     while (p != NULL)
     {
      q = p;
      p = p->next;
      delete q;
     }
     size = 0;
    }

    /*
    * 函数名称: Reset
    * 输 入: pos
    * pos: 数据元素结点的位置
    * 输 出:
    * 功能描述: 使currPtr指向结点pos,并返回currPtr
    * 作 者: 吴友强
    * 日 期: 2009年10月13日
    * 修 改:
    * 日 期:
    */
    template <class T>
    ListNode<T> *LinkList<T>::Reset(int pos)
    {
     if (pos < -1 || pos > size - 1)
     {
      cout << "参数pos越界出错!" << endl;
      exit(0);
     }

     if (pos == -1)
     {
      return head;
     }

     if (pos == 0)
     {
      currPtr = head->next;
     }
     else
     {
      currPtr = head->next;
      ListNode<T> prevPtr = head;
      for (int i=0; i<pos; i++)
      {
       prevPtr = currPtr;
       currPtr = currPtr->next;
      }
     }

     return currPtr;
    }

    /*
    * 函数名称: Next
    * 输 入: 
    * 输 出:
    * 功能描述: 使currPtr指向下一个结点
    * 作 者: 吴友强
    * 日 期: 2009年10月13日
    * 修 改:
    * 日 期:
    */
    template <class T>
    ListNode<T> *LinkList<T>::Next(void)
    {
     if (currPtr != NULL)
     {
      currPtr = currPtr->next;
     }

     return currPtr;
    }

    /*
    * 函数名称: EndOfList
    * 输 入: 
    * 输 出:
    * 功能描述: currPtr是否指在链表尾
    * 作 者: 吴友强
    * 日 期: 2009年10月13日
    * 修 改:
    * 日 期:
    */
    template <class T>
    int LinkList<T>::EndOfList(void) const
    {
     return currPtr == NULL ? 1 : 0;
    }

    /*
    * 函数名称: GetData
    * 输 入: pos
    * pos: 需要得到结点数据的位置
    * 输 出:
    * 功能描述: 获取pos处结点的数据
    * 作 者: 吴友强
    * 日 期: 2009年10月13日
    * 修 改:
    * 日 期:
    */
    template <class T>
    T LinkList<T>::GetData(int pos)
    {
     if (pos < 0 || pos > size-1)
     {
      cout << "参数pos越界出错!" << endl;
      exit(0);
     }

     ListNode<T> *p = Index(pos);
     return p->data;
    }

     

    4.LinkListTest.cpp测试程序:

    /*
    * Copyright (c) 2009,FreshAir团队嵌入式软件研发组
    * All rights reserved.
    *
    * 文件名称:SeqListTest.cpp
    * 摘 要: 测试链表的功能
    *
    * 当前版本:1.0
    * 作 者: 吴友强
    * 完成日期:2009年10月13日
    *
    * 取代版本:
    * 原作者 :
    * 完成日期:
    */

    #include <iostream.h>
    #include <stdlib.h>

    #include "LinkList.h"

    int main(int argc, char *argv[])
    {
     LinkList<int> targetList, sourceList;

     for (int i=0; i<10; i++)
     {
      targetList.Insert(i+10, i);
     }

     for (i=0; i<5; i++)
     {
      sourceList.Insert(i+5, i);
     }
    //  cout << "测试GetData()成员函数结果如下:" << endl;
    //  int n = linkList.GetListSize();
    //  for (i=0; i<n; i++)
    //  {
    //   cout << linkList.GetData(i) << " ";
    //  }
    //
    //  cout << endl << "测试遍历成员函数结果如下:" << endl;
    //  ListNode<int> *p = linkList.Reset(0);
    //
    //  while (!linkList.EndOfList())
    //  {
    //   cout << p->data << " ";
    //   p = linkList.Next();
    //  }
    //
    //  cout << endl << "测试Delete()成员函数结果如下:" << endl;
    //  n = linkList.GetListSize();
    //  for (i=n-1; i>=0; i--)
    //  {
    //   linkList.Delete(i);
    //  }
    //
    //  cout << "测试GetData()成员函数结果如下:" << endl;
    //  n = linkList.GetListSize();
    //  for (i=0; i<n; i++)
    //  {
    //   cout << linkList.GetData(i) << " ";
    //  }

     Concatenate(targetList, sourceList);

     int n = targetList.GetListSize();
     for (i=0; i<n; i++)
     {
      cout << targetList.GetData(i) << " ";
     }
     return 0;
    }

    5.注意事项:(1)如果单链表的定义与接口的实现分开到两个不同的头文件和CPP文件,编译会出错,解决把法是把CPP文件删除在头文件最后加上一句:#include "LinkList.cpp"

    (2)上面注释部分是测试基本函数功能的,我同时在里面测试了提高要求2,提高2的现实在下一篇中给出。

     

  • 相关阅读:
    spring2.5 mvc使用注解upload上传文件
    从5点来分析搜索引擎算法
    搜索引擎算法研究专题六:HITS算法
    搜索引擎算法研究专题五:TFIDF详解
    搜索引擎算法研究专题二:HITS算法及其衍生算法分析
    搜索引擎算法研究专题一:基于页面分块的搜索引擎排序算法改进
    搜索引擎算法研究专题三:聚集索引与非聚集索引介绍
    Spring最佳实践9.1 集成邮件服务
    搜索引擎算法研究专题四:随机冲浪模型介绍
    搜索引擎算法研究专题七:Hilltop算法
  • 原文地址:https://www.cnblogs.com/brucewoo/p/2252050.html
Copyright © 2011-2022 走看看