`
dato0123
  • 浏览: 913549 次
文章分类
社区版块
存档分类
最新评论

数据结构学习记录连载4(上一篇中提高要求实现)

 
阅读更多

1.给出提高要求2的函数实现

/*
* 函数名称: Concatenate
* 输 入:source,target
*source:需要连接的对象
*target:被连接的对象
* 输 出:
* 功能描述: 将对象source连接到单链表target的尾部
* 作 者:吴友强
* 日 期:2009年10月13日
* 修 改:
* 日 期:
*/
template <class T>
void Concatenate(LinkList<T>& target, LinkList<T>& source)
{
ListNode<T> *q = source.head;

while (q->next != NULL)
{
target.Insert(q->next->data, target.size);
q = q->next;
}
}

注意事项:实现时不要直接把两个链表连接起来就好了,这样造成同一块内存会释放两遍,造成运行完时报错,其实就是析构函数中出错。

而是需要用要到深拷贝的原理实现,就是取出source的数据插入到target中。上一篇中以给出测试程序。

2.提高要求2的实现:说明:本来只是修改上一篇中某些函数的实现就可以了,但是作为程序的完整性我在这里也全部给出

(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;//指向下一个结点的指针
ListNode<T> *prev;//指向上一个结点的指针
public:
T data;
ListNode(ListNode<T> *ptrNext=NULL, ListNode<T> *ptrPrev=NULL);//构造函数,用于构造头结点
ListNode(const T& item, ListNode<T> *ptrNext, ListNode<T> *ptrPrev);//构造函数,非头结点
~ListNode() {};//析构函数
friend void Concatenate(LinkList<T>& target, LinkList<T>& souce);
};

template<class T>
ListNode<T>::ListNode(ListNode<T> *ptrNext, ListNode<T> *ptrPrev)
:next(ptrNext),prev(ptrPrev)
{

}

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

(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>();
head->next = head;
head->prev = head;
}

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);
ListNode<T> *newNode = new ListNode<T>(item, NULL, NULL);

newNode->prev = p->prev;
newNode->next = p;
p->prev->next = newNode;
p->prev = newNode;

size++;
}

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

ListNode<T> *p = Index(pos);
p->prev->next = p->next;
p->next->prev = p->prev;
temp = p->data;
delete p;
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 != head)
{
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;
}

/*
* 函数名称: Concatenate
* 输 入:source,target
*source:需要连接的对象
*target:被连接的对象
* 输 出:
* 功能描述: 将对象source连接到单链表target的尾部
* 作 者:吴友强
* 日 期:2009年10月13日
* 修 改:
* 日 期:
*/
template <class T>
void Concatenate(LinkList<T>& target, LinkList<T>& source)
{
ListNode<T> *q = source.head;

while (q->next != NULL)
{
target.Insert(q->next->data, target.size);
q = q->next;
}
}

(3)LinkListTest.cpp测试程序:

/*
* Copyright (c) 2009,FreshAir团队嵌入式软件研发组
* All rights reserved.
*
* 文件名称:LinkListTest.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) << " ";
// }

LinkList<int> myList;

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

cout << "插入100个元素输出如下:" << endl;
int n = myList.GetListSize();
for (i=0; i<n; i++)
{
cout << myList.GetData(i) << " ";
}

for (i=99; i>=0; i--)
{
myList.Delete(i);
}
cout << endl << "删除100个元素输出如下:" << endl;
n = myList.GetListSize();
for (i=0; i<n; i++)
{
cout << myList.GetData(i) << " ";
}
return 0;
}

说明:注释部分测试基本功能函数,其他测试提高要求。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics