_11 《数据结构、算法与应用C++语言描述》线性表-链表描述
11表示第11篇博文,6表示在 数据结构算法与应用C++语言描述 书中所在章节。
本文包含了《数据结构、算法与应用C++语言描述》第六章主要练习题答案,给出了线性表链表描述完整测试代码。
6.1 线性表数据结构
6.1.1 定义
线性表(linear list)也称有序表(ordered list),它的每一个实例都是元素的一个有序集合。每一个实例的形式为(
e
0
e_0
e0?,
e
1
e_1
e1?,…,
e
n
?
1
e_{n-1}
en?1?),其中n是有穷自然数,
e
i
e_i
ei?是线性表的元素,i是元素
e
i
e_i
ei?的索引,n是线性表的长度或大小。元素可以被看做原子,它们本身的结构与线性表的结构无关。当n=0时,线性表为空;当n>0时,
e
0
e_0
e0?是线性表的第0个元素或首元素,
e
n
?
1
e_{n-1}
en?1?是线性表的最后一个元素。可以认为
e
0
e_{0}
e0?先于
e
1
e_{1}
e1?,
e
1
e_{1}
e1?先于
e
2
e_{2}
e2?,等等。除了这种先后关系之外,线性表不再有其他关系。
6.1.2 举例
- 1)一个班级的学生按姓名的字母顺序排列的列表;
- 2)按非递减次序排列的考试分数表;
- 3)按字母顺序排列的会议列表;
- 4)奥林匹克男子篮球比赛的金牌获得者按年代次序排列的列表。
6.1.3 线性表的抽象数据类型
抽象数据类型(abstract data type,ADT),既能说明数据结构的实例,也说明对它的操作。抽象数据类型的说明独立于任何程序语言的描述。所有对抽象数据类型的语言描述必须满足抽象数据类型的说明,抽象数据类型的说明保证了程序语言描述的有效性。另外,所有满足抽象数据类型说明的语言描述,都可以在应用中替换使用。
抽象数据类型linearList
{
实例
有限个元素的有序集合
操作
empty():若表空,则返回true,否则返回false
size():返回线性表的大小(表的元素个数)
get(index):返回线性表中索引为index的元素
indexOf(x):返回线性表中第一次出现的x的索引。若x不存在,则返回-1
erase(index):删除索引为index的元素,索引大于index的元素其索引减1
insert(index,x):把x插人线性表中索引为index的位置上,索引大于等于index的元素其索引加1
output():从左到右输出表元素
}
6.1.4 抽象类linearList
抽象类
一个抽象类包含着没有实现代码的成员函数。这样的成员函数称为纯虚函数(pure virtual function)。纯虚函数用数字0作为初始值来说明,形式如下:
virtual int myPurevirtualFunction(int x)=0;
抽象数据类型不依赖程序语言,C++抽象类依赖程序语言。可以建立抽象类的对象指针。
抽象类的派生类,只有实现了基类的所有纯虚函数才是具体类,否则依然是抽象类而不能实例化。 具体类
具体类是没有纯虚函数的类。只有具体类才可以实例化。也就是说,我们只能对具体类建立实例或对象。
linearList抽象类定义
将抽象类的析构函数定义为虚函数,目的是,当一个线性表的实例离开作用域时需要调用的缺省析构函数时引用对象中数据类型的析构函数。
#pragma once
#ifndef __LINEARLIST_H_
#define __LINEARLIST_H_
#include<iostream>
using std::ostream;
template <class T>
class linearList
{
public:
virtual ~linearList() {};
virtual bool empty() const = 0;
virtual int size() const = 0;
virtual T& get(int theIndex) const = 0;
virtual int indexOf(const T& theElement) const = 0;
virtual void erase(int theIndex) = 0;
virtual void insert(int theIndex, const T& theElement) = 0;
virtual void output(ostream& out) const = 0;
};
#endif
6.2 链表描述
6.2.1 单链表
设L=(
e
0
e_0
e0?,
e
1
e_1
e1?,…,
e
n
?
1
e_{n-1}
en?1?)是一个线性表。在对这个线性表的一个可能的链式描述中,每个元素都在一个单独的节点中描述,每一个节点都有一个链域,它的值是线性表的下一个元素的位置,即地址。这样一来,元素
e
i
e_{i}
ei?的节点链接着元素
e
i
+
1
e_{i+1}
ei+1?的节点,0<=i<n-1。元素
e
n
?
1
e_{n-1}
en?1?的节点没有其他节点可链接,因此链域的值为NULL。
每一个节点只有一条链,这种结构称为单链表。
原则上,数组适合查询比较频繁的数据存储,链表适合插入和删除比较频繁的数据存储,但是由于高速缓存容量的问题,导致单链表的插入和删除操作的运行时间高于数组。
也就是说,对于单表而言,性能比不上数组;但是对于某些特殊应用而言,比如把一个链表的尾节点和另一个链表的首节点链接起来,合并为一个链表,对于链表合并的时间复杂度为O(1),对于数组的时间复杂度比O(1)大。
6.2.2 循环链表
1)把线性表描述成一个单向循环链表(singly linked circular list)(简称循环链表);只要将单向链表的尾节点与头节点链接起来,单向链表就成为循环链表。
2)在链表的前面增加一个节点,称为头节点(header node)。使用头节点的链表非常普遍,这样可以使程序更简洁、运行速度更快。
6.2.3 双向链表
双向链表(doubly linked list)的每个节点都有两个指针:next 和previous。next指针指向右边节点(如果存在),previous指针指向左边节点(如果存在)。当双向链表只有一个元素节点p时,firstNode=lastNode=p。当双向链表为空时,firstNode=lastNode=NULL。
6.3 链表应用
6.3.1 箱子排序
用链表保存班级学生清单。节点的数据域有:学生姓名、社会保险号码、每次作业和考试的分数、所有作业和考试的加权总分。假设分数是0~ 100的整数,要求按总分排序。
箱子排序(bin sort)就是首先把分数相同的节点放在同一个箱子里,然后把箱子链接起来就得到有序的链表。
通用箱子排序步骤:
1)逐个删除输入链表的节点,把删除的节点分配到相应的箱子里;
2)把每一个箱子中的链表收集并链接起来,使其成为一个有序链表。
链表箱子排序步骤:
1)连续删除链表的首元素,并将其插入相应的某个箱子的链表首位;
2)从最后一个箱子开始,逐个删除每个箱子的元素,并将其插人一个初始为空的链表的首位。
稳定排序(stable sort):排序方法能够保持同值元素之间的相对次序,箱子排序就是稳定排序。
6.3.2 基数排序
定义
基数排序可以仅在Θ(n)时间内,就可以对0~
n
c
?
1
n^c-1
nc?1之间的n个整数进行排序,其中c>=0是一个整数常量。如果用原来的箱子排序方法对range=
n
c
n^{c}
nc来排序,则复杂度为
Θ
(
n
+
r
a
n
g
e
)
=
O
(
n
c
)
Θ(n+range)=O(n^{c})
Θ(n+range)=O(nc)。扩展后的方法与binSort不同,它不直接对数进行排序,而是把数(number)按照某种基数(radix)分解为数字(digit),然后对数字排序。基数可以根据需要选择。
举例
例6-1 假定对0~999之间的10个整数进行排序。如果使用range=1000的箱子排序方法,那么箱子链表的初始化需要1000个执行步,节点分配需要10个执行步,从箱子中收集节点需要1000个执行步,总的执行步数为2010。而基数排序方法是: 1)利用箱子排序方法,根据最低位数字(即个位数字),对10个数进行排序。因为每个数字都在0~9之间,所以range=10。
2)利用箱子排序方法,对1)的结果按次低位数字(即十位数字)进行排序。同样有range=10。因为箱子排序是稳定排序,所以次低位数字相同的节点,按最低位数字排序所得到的次序保持不变。因此,现在的链表是按照最后两位数字进行排序的。
3)利用箱子排序方法,对2)的结果按第三位数字(即百位数字)进行排序。小于100的数,第三位数字为0。因为按第三位数字排序是稳定排序,所以第三位数字相同的节点,按最后两位数字排序所得到的次序保持不变。因此,现在的链表是按照后三位数字进行排序的。
数字分解式
对于一般的基数r,相应的分解式为:
当使用基数r=n对0~
n
c
?
1
n^{c}-1
nc?1范围内的n个整数进行分解时,每个数可以分解出c个数字。因此,对n个数,可以用c次range=n个箱子排序。因为c是一个常量,所以整个排序时间为Θ(cn)=Θ(n)。
6.4 课后习题–单链表实现
- 2.编写方法chain::setSize(int theSize),它使线性表的大小等于theSize。若初始线性表的大小小于theSize,则不增加元素。若初始线性表的大小大于theSize,则删除多余的元素。计算方法的复杂度。测试你的代码。
- 3.编写方法chain::set(theIndex,theElement),它用元素theElement替换索引为thelndex的元素。若索引theIndex超出范围,则抛出异常。计算方法的复杂度。测试你的代码。
- 4.编写方法chain::removeRange(fromIndex,tolndex),它删除指定索引范围内的所有元素。
计算方法的复杂度。测试你的代码。 - 5.编写方法chain::lastIndexOf(theElement),返回值是指定元素最后出现时的索引。若这样的元素不存在,则返回-1。计算方法的复杂度。测试你的代码。
- 6.重载操作符[],使得表达式x[i]返回对链表x的第i个元素的引用。若链表没有第i个元素,则抛出异常illegalIndex。语句x[i]=y和y=x[i]按以往预期的方式执行。测试你的代码。
- 7.重载操作符==,使得表达式x==y返回true,当且仅当两个链表x和y相等,即对所有的i,两个链表的第i个元素相等。测试你的代码。
- 8.重载操作符!=,使得表达式x!=y返回true,当且仅当两个链表x和y不等(见练习7)。测试你的代码。
- 9.重载操作符<,使得表达式x<y返回true,当且仅当链表x按字典顺序小于链表y(见练习7)。测试你的代码。
- 10.编写方法chain::swap(theChain),它交换链表元素*this和theChain。计算方法的复杂度。测试你的代码。
- 11.编写一个方法,它把数组线性表转换为链表。这个方法既不是类arrayList的成员函数,也不是类chain的成员函数。使用类arrayList的方法get和类chain的方法insert。计算方法的复杂度。测试你的代码。
- 12.编写一个方法,它把链表转换为数组线性表。这个方法既不是类arrayList的成员函数,也不是类chain的成员函数。
1)使用类chain的get方法和listSize方法,类arrayList的insert方法。计算方法的复杂度。测试你的代码。 2)使用链表选代器。计算方法的复杂度。设计数据测试你的代码。 - 13.在类chain中增加转换方法。一个方法是fromList(theList),它把数组线性表theList转换为链表。另一个方法是toList(theList),它把链表*this转换为数组线性表theList。计算方法的复杂度。测试你的代码。
- 14.1)编写方法chain::leftShift(i),它将表中的元素向左移动i个位置。如果l=[0,1,2,3,4],那么l.leftShift(2)的结果是1=[2,3,4]。
2)计算方法的复杂度。 3)测试你的代码。 - 15.1)编写方法chain::reverse,它颠倒*this中的元素的顺序,而且原地完成,不用分配任何新的节点空间。
2)计算方法的复杂度。 3)使用自己的测试数据检验方法的正确性。 - 18.编写方法chain::meld。它生成一个新的扩展的链表c,它从a的首元素开始,交替地包含a和b的元素。如果一个链表的元素取完了,就把另一个链表的剩余元素附加到新的扩展链表c中。方法的复杂度应与链表a和b的长度具有线性关系。合并后的链表使用的应该是链表a和b的节点空间。合并之后,输入链表a和b是空表。
1)编写方法meld,其复杂度应该与输入链表的长度具有线性关系。 2)证明方法具有线性复杂度。 3)测试代码的正确性。使用自己的测试数据。 - 20.令a和b的类型为chain。假设a和b的元素类型都定义了操作符<、>、=、==和!=。而且假设a和b是有序链表(从左至右非逆减)。
1)编写一个非成员方法merge,它生成一个新的有序链表c,包含a和b的所有元素。归并之后,两个输入链表a和b为空。 2)计算方法的复杂度。 3)使用自己的测试数据检验方法的正确性。 - 22.令c的类型为扩展链表chain。
1)编写一个成员方法split(a,b),它生成两个链表a和b。a包含*this中索引为奇数的元素,b包含*this中其余的元素。调用此方法后*this变为空链表 2)计算方法的复杂度。 3)使用自己的测试数据检验方法的正确性。 - 23.在一个循环移动的操作中,线性表的元素根据给定的值,按顺时针方向移动。例如L=[0,1,2,3,4],循环移动2的结果是L=[2,3,4,0,1]。
1)编写方法chain::circularShift(i),它将线性表的元素循环移动i个位置。 2)测试你的代码。
6.5 单链表完整测试代码
_1myExceptions.h
#pragma once
#ifndef _MYEXCEPTIONS_H_
#define _MYEXCEPTIONS_H_
#include <string>
#include<iostream>
using namespace std;
class illegalParameterValue
{
public:
illegalParameterValue(string theMessage = "Illegal parameter value")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
class illegalInputData
{
public:
illegalInputData(string theMessage = "Illegal data input")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
class illegalIndex
{
public:
illegalIndex(string theMessage = "Illegal index")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
class matrixIndexOutOfBounds
{
public:
matrixIndexOutOfBounds
(string theMessage = "Matrix index out of bounds")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
class matrixSizeMismatch
{
public:
matrixSizeMismatch(string theMessage =
"The size of the two matrics doesn't match")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
class stackEmpty
{
public:
stackEmpty(string theMessage =
"Invalid operation on empty stack")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
class queueEmpty
{
public:
queueEmpty(string theMessage =
"Invalid operation on empty queue")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
class hashTableFull
{
public:
hashTableFull(string theMessage =
"The hash table is full")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
class undefinedEdgeWeight
{
public:
undefinedEdgeWeight(string theMessage =
"No edge weights defined")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
class undefinedMethod
{
public:
undefinedMethod(string theMessage =
"This method is undefined")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
#endif
_2myFunctions.h
#pragma once
#ifndef _MYFUNCTIONS_H_
#define _MYFUNCTIONS_H_
#include<iostream>
#include "_1myExceptions.h"
#include<cmath>
#include <exception>
using std::min;
using std::endl;
using std::cout;
using std::bad_alloc;
template<class V>
void Swap(V& a, V& b)
{
V temp = a;
a = b;
b = temp;
}
template<class T>
void changeLength(T*& a, int oldLength, int newLength)
{
if (newLength < 0)
throw illegalParameterValue("new length must be >= 0");
T* temp = new T[newLength];
int number = min(oldLength, newLength);
copy(a, a + number, temp);
delete[] a;
a = temp;
}
template<class T>
void traverse1dArray(T* x, int length)
{
for (int i = 0; i < length; i++)
cout << x[i] << " ";
cout << endl;
}
template <class T>
bool make2dArray(T**& x, int numberOfRows, int numberOfColumns)
{
try {
x = new T * [numberOfRows];
for (int i = 0; i < numberOfRows; i++)
x[i] = new int[numberOfColumns];
return true;
}
catch (bad_alloc) { return false; }
}
template<class T>
void traverse2dArray(T**& x, int numberOfRows, int numberOfColumns)
{
for (int i = 0; i < numberOfRows; i++)
{
for (int j = 0; j < numberOfColumns; j++)
{
cout.width(4);
cout << x[i][j] << " ";
}
cout << endl;
}
}
void myFunctionsTest();
void towersOfHanoiRecursion(int n, int x, int y, int z);
#endif
_4linearList.h–线性表抽象类
#pragma once
#ifndef __LINEARLIST_H_
#define __LINEARLIST_H_
#include<iostream>
using std::ostream;
template <class T>
class linearList
{
public:
virtual ~linearList() {};
virtual bool empty() const = 0;
virtual int size() const = 0;
virtual T& get(int theIndex) const = 0;
virtual int indexOf(const T& theElement) const = 0;
virtual void erase(int theIndex) = 0;
virtual void insert(int theIndex, const T& theElement) = 0;
virtual void output(ostream& out) const = 0;
};
#endif
_5arrayList.h
#pragma once
#ifndef __ARRAYLIST_H_
#define __ARRAYLIST_H_
#include <algorithm>
#include<iostream>
#include<sstream>
#include<cmath>
#include<cstddef>
#include <iterator>
#include "_1myExceptions.h"
#include "_2myFunctions.h"
#include "_4linearList.h"
using std::ostream;
using std::ostringstream;
using std::find;
using std::cout;
using std::copy;
using std::min;
using std::copy_backward;
using std::ostream_iterator;
using std::bidirectional_iterator_tag;
using std::ptrdiff_t;
template<class T>
class chain;
void arrayListTest();
template<class T>
class arrayList : public linearList<T>
{
public:
arrayList(int initialCapacity = 1);
arrayList(const arrayList<T>&);
arrayList(const chain<T>& theChain);
~arrayList() { delete[] element; }
bool empty() const { return arraySize == 0; }
int size() const { return arraySize; }
T& get(int theIndex) const;
int indexOf(const T& theElement) const;
void erase(int theIndex);
void insert(int theIndex, const T& theElement);
void insert(int theIndex, const T& theElement,int size);
void output(ostream& out) const;
void trimToSize();
int capacity() const { return arrayLength; }
void push_back(const T& theElement);
T pop_back();
void swap(arrayList<T>& theList);
void reserve(int theCapacity);
void set(int theIndex, const T& theElement);
void clear();
void removeRange(int theIndex1, int theIndex2);
int lastIndexOf(T theElement);
void reverse();
void leftShift(int num);
void circularShift(int i);
void half();
void meld(arrayList<T>& a, arrayList<T>& b);
void merge(arrayList<T>& a, arrayList<T>& b);
void split(arrayList<T>& a, arrayList<T>& b);
void reSet(int capacity);
class iterator
{
public:
typedef bidirectional_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
iterator(T* thePosition = 0) { position = thePosition; }
T& operator*() const { return *position; }
T* operator->() const { return &*position; }
iterator& operator++()
{
++position;
return *this;
}
iterator operator++(int)
{
iterator old = *this;
++position;
return old;
}
iterator& operator--()
{
--position;
return *this;
}
iterator operator--(int)
{
iterator old = *this;
--position;
return old;
}
bool operator!=(const iterator right) const
{
return position != right.position;
}
bool operator==(const iterator right) const
{
return position == right.position;
}
protected:
T* position;
};
iterator begin() { return iterator(element); }
iterator end() { return iterator(element + arraySize); }
T& operator[](int i);
const T& operator[](int i) const;
bool operator==(arrayList<T> right) const;
bool operator!=(arrayList<T> right) const;
bool operator<(arrayList<T> right) const;
void bubbleSort();
void rankSort();
int indexOfMax();
void selectionSort();
void insertSort();
friend istream& operator>> <T>(istream& in, arrayList<T>& m);
protected:
void checkIndex(int theIndex) const;
void setLength(int Length) { arrayLength = Length; }
void setSize(int Size) { arraySize = Size; }
void setElement(T* theElement) { element = theElement; }
T* address() const { return element; }
T* element;
int arrayLength;
int arraySize;
};
template<class T>
arrayList<T>::arrayList(int initialCapacity)
{
if ( initialCapacity < 1 )
{
ostringstream s("");
s << "Initial capacity = " << initialCapacity << "Must be > 0";
throw illegalParameterValue(s.str());
}
arrayLength = initialCapacity;
element = new T[arrayLength];
arraySize = 0;
}
template<class T>
arrayList<T>::arrayList(const arrayList<T>& theList)
{
arrayLength = theList.arrayLength;
arraySize = theList.arraySize;
element = new T[arrayLength];
copy(theList.element, theList.element + arraySize, element);
}
template<class T>
arrayList<T>::arrayList(const chain<T>& theChain)
{
arraySize = theChain.size();
arrayLength = arraySize;
element = new T[arraySize];
typename chain<T>::iterator pointer = theChain.begin();
int i = 0;
while (pointer != nullptr)
{
*(element + i) = *pointer;
pointer++;
i++;
}
}
template<class T>
void arrayList<T>::checkIndex(int theIndex) const
{
if (theIndex < 0 || theIndex >= arraySize)
{
ostringstream s("");
s << "index = " << theIndex << "size = "<<arraySize;
throw illegalIndex(s.str());
}
}
template<class T>
T& arrayList<T>::get(int theIndex) const
{
checkIndex(theIndex);
return element[theIndex];
}
template<class T>
int arrayList<T>::indexOf(const T& theElement) const
{
int theIndex = (int)(find(element, element + arraySize, theElement) - element);
if (theIndex == arraySize)
return -1;
else
return theIndex;
}
template<class T>
void arrayList<T>::trimToSize()
{
if (arraySize == 0)
{
changeLength(element, arrayLength, 1);
arrayLength = 1;
}
}
template<class T>
void arrayList<T>::erase(int theIndex)
{
checkIndex(theIndex);
copy(element + theIndex + 1, element + arraySize, element + theIndex);
element[--arraySize].~T();
trimToSize();
while (arraySize < arrayLength / 4)
{
changeLength(element, arrayLength, arrayLength / 2);
arrayLength /= 2;
}
}
template<class T>
void arrayList<T>::insert(int theIndex, const T& theElement)
{
if(theIndex != 0 && theIndex != arraySize)
checkIndex(theIndex);
if (arraySize == arrayLength)
{
changeLength(element, arrayLength, 2 * arrayLength);
arrayLength *= 2;
}
copy_backward(element + theIndex, element + arraySize, element + arraySize + 1);
element[theIndex] = theElement;
arraySize += 1;
}
template<class T>
void arrayList<T>::insert(int theIndex, const T& theElement,int size)
{
if(theIndex != 0 && theIndex != arraySize)
checkIndex(theIndex);
if (arraySize == arrayLength)
{
changeLength(element, arrayLength, size);
arrayLength = size;
}
copy_backward(element + theIndex, element + arraySize, element + arraySize + 1);
element[theIndex] = theElement;
arraySize += 1;
}
template<class T>
void arrayList<T>::output(ostream& out) const
{
copy(element, element + arraySize, ostream_iterator<T>(cout, " "));
}
template<class T>
void arrayList<T>::push_back(const T& theElement)
{
if (arraySize == arrayLength)
{
changeLength(element, arrayLength, arrayLength*2);
arrayLength = arrayLength * 2;
}
*(element + arraySize) = theElement;
arraySize++;
}
template<class T>
T arrayList<T>::pop_back()
{
checkIndex(arraySize-1);
T temp = element[arraySize - 1];
arraySize--;
trimToSize();
while (arraySize < arrayLength / 4)
{
changeLength(element, arrayLength, arrayLength / 2);
arrayLength /= 2;
}
return temp;
}
template<class T>
void arrayList<T>::swap(arrayList<T>& theList)
{
T* temp = element;
int thisLength = arrayLength;
int thisSize = arraySize;
element = theList.address();
arraySize = theList.size();
arrayLength = theList.capacity();
theList.setSize(thisSize);
theList.setLength(thisLength);
theList.setElement(temp);
}
template<class T>
void arrayList<T>::reserve(int theCapacity)
{
if (arrayLength < theCapacity)
{
T* temp = new T[theCapacity];
for (int i = 0; i < arraySize; i++)
{
temp[i] = element[i];
}
delete[] element;
element = temp;
arrayLength = theCapacity;
}
}
template<class T>
void arrayList<T>::set(int theIndex, const T& theElement)
{
checkIndex(theIndex);
element[theIndex] = theElement;
}
template<class T>
void arrayList<T>::clear()
{
arraySize = 0;
trimToSize();
}
template<class T>
void arrayList<T>::removeRange(int theIndex1, int theIndex2)
{
checkIndex(theIndex1);
checkIndex(theIndex2);
for (int i = theIndex1; i < arraySize - (theIndex2 - theIndex1); i++)
{
element[i] = element[i + theIndex2 - theIndex1 + 1];
}
arraySize -= theIndex2 - theIndex1 + 1;
}
template<class T>
int arrayList<T>::lastIndexOf(T theElement)
{
for (int i = arraySize - 1; i >= 0; i--)
{
if (element[i] == theElement)
return i;
}
return -1;
}
template<class T>
void arrayList<T>::reverse()
{
for (int i = 0; i < arraySize / 2; i++)
Swap<T>(element[i], element[arraySize - i - 1]);
}
template<class T>
void arrayList<T>::leftShift(int num)
{
checkIndex(num-1);
for (int i = 0; i < arraySize - num + 1; i++)
{
element[i] = element[i + num];
}
arraySize -= num;
}
template<class T>
void arrayList<T>::circularShift(int num)
{
for(int i = 0; i < num; i++)
push_back(element[i]);
leftShift(num);
}
template<class T>
void arrayList<T>::half()
{
for (int i = 1; i <= (arraySize+1) / 2; i++)
element[i] = element[2 * i];
arraySize = (arraySize+1) / 2;
}
template <class T>
void arrayList<T>::meld(arrayList<T>& a, arrayList<T>& b)
{
(*this).clear();
int i = 0;
while (i < a.size() && i < b.size())
{
push_back(a[i]);
push_back(b[i]);
i++;
}
while (i < a.size())
{
push_back(a[i]);
i++;
}
while (i < b.size())
{
push_back(b[i]);
i++;
}
}
template<class T>
void arrayList<T>::merge(arrayList<T>& a, arrayList<T>& b)
{
(*this).clear();
int i = 0;
int j = 0;
while ((i < a.size()) && (j < b.size()))
{
if (a[i] < b[j])
{
push_back(a[i]);
i++;
}
else if (a[i] == b[j])
{
push_back(a[i]);
push_back(b[j]);
i++;
j++;
}
else
{
push_back(b[j]);
j++;
}
}
while (i < a.size())
{
push_back(a[i]);
i++;
}
while (j < b.size())
{
push_back(b[j]);
j++;
}
}
template<class T>
void arrayList<T>::split(arrayList<T>& a, arrayList<T>& b)
{
a.clear();
b.clear();
for (int i = 0; i < arraySize; i++)
{
if (i % 2 == 0)
a.push_back(element[i]);
else
b.push_back(element[i]);
}
}
template<class T>
void arrayList<T>::reSet(int capacity)
{
if (capacity < 0)
throw illegalParameterValue("capacity must be >= 0");
T* temp = new T[capacity];
delete[] element;
element = temp;
arraySize = capacity;
}
template<class T>
istream& operator>>(istream& in, arrayList<T>& m)
{
int numberOfElement = 0;
cout << "Please enter the number of elements:" << endl;
while (!(in >> numberOfElement)) {
in.clear();
while (in.get() != '\n')
continue;
cout << "Please enter the number of elements:" << endl;
}
T inElement = 0;
for (int i = 0; i < numberOfElement; i++)
{
cout << "Please enter the element: " << (i + 1) << endl;
while (!(in >> inElement)) {
in.clear();
while (in.get() != '\n')
continue;
cout << "Please enter the element: " << (i + 1) << endl;
}
m.push_back(inElement);
}
return in;
}
template<class T>
ostream& operator<<(ostream& out, const arrayList<T>& x)
{
x.output(out);
return out;
}
template<class T>
T& arrayList<T>::operator[](int i)
{
return element[i];
}
template<class T>
const T& arrayList<T>::operator[](int i) const
{
return element[i];
}
template<class T>
bool arrayList<T>::operator==(arrayList<T> right) const
{
if (arraySize == right.size())
{
for (int i = 0; i < arraySize; i++)
{
if ((*this)[i] != right[i])
return false;
}
return true;
}
else
return false;
}
template<class T>
bool arrayList<T>::operator!=(arrayList<T> right) const
{
if (arraySize == right.size())
{
for (int i = 0; i < arraySize; i++)
{
if ((*this)[i] != right[i])
return true;
}
return false;
}
else
return true;
}
template<class T>
bool arrayList<T>::operator<(arrayList<T> right) const
{
if (arraySize <= right.size())
{
for (int i = 0; i < arraySize; i++)
{
if ((*this)[i] >= right[i])
return false;
}
return true;
}
else
return false;
}
template<class T>
void arrayList<T>::bubbleSort()
{
bool is_sorted = true;
for (int i = arraySize; is_sorted && i > 1; i--)
{
is_sorted = false;
for (int j = 0; j < i - 1; j++)
{
if (element[j] > element[j + 1])
{
Swap<T>(element[j], element[j + 1]);
is_sorted = true;
}
}
}
}
template<class T>
void arrayList<T>::rankSort()
{
int* r = new int[arraySize];
for (int i = 0; i < arraySize; i++)
r[i] = 0;
for (int i = arraySize - 1; i >= 0; i--)
{
for (int j = 0; j < i ; j++)
{
if (*(element + i) > *(element + j))
r[i]++;
else
r[j]++;
}
}
for (int i = 0; i < arraySize; i++)
{
if (i != r[i])
{
Swap<T>(element[i], element[r[i]]);
Swap<T>(r[i], r[r[i]]);
}
}
delete[] r;
}
template<class T>
int arrayList<T>::indexOfMax()
{
int indexMax = 0;
for (int i = 1; i < arraySize; i++)
{
if (element[i] > element[indexMax])
{
indexMax = i;
}
}
return indexMax;
}
template<class T>
void arrayList<T>::selectionSort()
{
bool is_sorted = false;
for (int i = arraySize; i > 1 && !is_sorted; i--)
{
is_sorted = true;
int indexMax = 0;
for (int j = 1; j < i; j++)
{
if (element[j] > element[indexMax])
indexMax = j;
else
is_sorted = false;
}
Swap<T>(element[i - 1], element[indexMax]);
}
}
template<class T>
void arrayList<T>::insertSort()
{
int temp = 0;
for (int i = 1; i < arraySize; i++)
{
temp = element[i];
int j = 0;
for (j = i - 1; temp < element[j]; j--)
{
element[j + 1] = element[j];
}
element[j + 1] = temp;
}
}
#endif
_6chainNode.h–链表节点
#pragma once
#ifndef _CHAINNODE_H_
#define _CHAINNODE_H_
template <class T>
struct chainNode
{
T element;
chainNode<T>* next;
chainNode() {}
chainNode(const T& element)
{
this->element = element;
this->next = nullptr;
}
chainNode(const T& element, chainNode<T>* next)
{
this->element = element;
this->next = next;
}
};
#endif
_6chain.h
#pragma once
#ifndef _CHAIN_H_
#define _CHAIN_H_
#include<iostream>
#include<sstream>
#include<cmath>
#include "_1myExceptions.h"
#include "_2myFunctions.h"
#include "_4linearList.h"
#include "_5arrayList.h"
#include "_6chainNode.h"
using std::ostream;
using std::ostringstream;
using std::find;
using std::cout;
using std::forward_iterator_tag;
using std::ptrdiff_t;
using std::endl;
void chainTest();
template<class T>
class chain : public linearList<T>
{
public:
chain(int initialCapacity = 10);
chain(const chain<T>&);
chain(const arrayList<T>& arrayTo);
~chain();
bool empty() const { return listSize == 0; }
int size() const { return listSize; }
T& get(int theIndex) const;
int indexOf(const T& theElement) const;
void erase(int theIndex);
void insert(int theIndex, const T& theElement);
void output(ostream& out) const;
void clear();
void push_back(const T& theElement);
void setSize(int theSize);
void set(int theIndex, const T& theElement);
void removeRange(int fromIndex, int toIndex);
int lastIndexOf(const T& theElement);
void swap(chain<T>& theChain);
void toArray(arrayList<T>& theArray);
void leftShift(int i);
void reverse();
void meld(chain<T>& a, chain<T>& b);
void merge(chain<T>& a, chain<T>& b);
void split(chain<T>& a, chain<T>& b);
void circularShift(int i);
class iterator
{
public:
typedef forward_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
iterator(chainNode<T>* theNode = nullptr) { node = theNode; }
T& operator*() const { return node->element; }
T* operator->() const { return &node->element; }
iterator& operator++()
{
node = node->next; return *this;
}
iterator& operator++(int)
{
iterator old = *this;
node = node->next;
return old;
}
bool operator!=(const iterator right) const { return node != right.node; }
bool operator==(const iterator right) const { return node == right.node; }
protected:
chainNode<T>* node;
};
iterator begin() const { return iterator(firstNode); }
iterator end() const { return iterator(nullptr); }
T& operator[](int i);
const T& operator[](int i) const;
bool operator==(chain<T>& right) const;
bool operator!=(chain<T>& right) const;
bool operator<(chain<T>& right) const;
void bubbleSort();
void rankSort();
T maxOfList();
void selectionSort();
void insertSort();
void binSort(int range);
void baseBinSort(int range);
friend istream& operator>> <T>(istream& in, chain<T>& m);
protected:
void checkIndex(int theIndex) const;
chainNode<T>* firstNode;
int listSize;
};
template<class T>
istream& operator>>(istream& in, chain<T>& m)
{
int numberOfElement = 0;
cout << "Please enter the number of elements:" << endl;
while (!(in >> numberOfElement)) {
in.clear();
while (in.get() != '\n')
continue;
cout << "Please enter the number of elements:" << endl;
}
T inElement = 0;
for (int i = 0; i < numberOfElement; i++)
{
cout << "Please enter the element: " << (i + 1) << endl;
while (!(in >> inElement)) {
in.clear();
while (in.get() != '\n')
continue;
cout << "Please enter the element: " << (i + 1) << endl;
}
m.push_back(inElement);
}
return in;
}
template<class T>
chain<T>::chain(int initialCapacity)
{
if (initialCapacity < 1)
{
ostringstream s("");
s << "Initial capacity = " << initialCapacity << "Must be > 0";
throw illegalParameterValue(s.str());
}
firstNode = nullptr;
listSize = 0;
}
template<class T>
chain<T>::chain(const chain<T>& theList)
{
listSize = theList.listSize;
if (listSize == 0)
{
firstNode = nullptr;
return;
}
chainNode<T>* sourceNode = theList.firstNode;
firstNode = new chainNode<T>(sourceNode->element);
sourceNode = sourceNode->next;
chainNode<T>* targetNode = firstNode;
while (sourceNode != nullptr)
{
targetNode->next = new chainNode<T>(sourceNode->element);
targetNode = targetNode->next;
sourceNode = sourceNode->next;
}
}
template<class T>
chain<T>::chain(const arrayList<T>& arrayTo)
{
listSize = arrayTo.size();
if (listSize == 0)
{
firstNode = nullptr;
}
else
{
int data = arrayTo.get(0);
firstNode = new chainNode<T>(data);
chainNode<T>* currentNode = firstNode;
for (int i = 1; i < listSize; i++)
{
data = arrayTo.get(i);
currentNode->next = new chainNode<T>(data);
currentNode = currentNode->next;
}
}
}
template<class T>
chain<T>::~chain()
{
while (firstNode != nullptr)
{
chainNode<T>* nextNode = firstNode->next;
delete firstNode;
firstNode = nextNode;
}
}
template<class T>
void chain<T>::checkIndex(int theIndex) const
{
if (theIndex < 0 || theIndex >= listSize)
{
ostringstream s("");
s << "index = " << theIndex << "size = " << listSize;
throw illegalIndex(s.str());
}
}
template<class T>
T& chain<T>::get(int theIndex) const
{
checkIndex(theIndex);
chainNode<T>* currentNode = firstNode;
for (int i = 0; i < theIndex; i++)
currentNode = currentNode->next;
return currentNode->element;
}
template<class T>
int chain<T>::indexOf(const T& theElement) const
{
chainNode<T>* currentNode = firstNode;
int index = 0;
while (currentNode != NULL && currentNode->element != theElement)
{
index++;
currentNode = currentNode->next;
}
if (index == listSize)
return -1;
else
return index;
}
template<class T>
void chain<T>::erase(int theIndex)
{
checkIndex(theIndex);
chainNode<T>* deleteNode = nullptr;
if (theIndex == 0)
{
deleteNode = firstNode;
firstNode = firstNode->next;
}
else
{
chainNode<T>* currentNode = firstNode;
for (int i = 0; i < theIndex - 1; i++)
{
currentNode = currentNode->next;
}
deleteNode = currentNode->next;
currentNode->next = currentNode->next->next;
}
delete deleteNode;
listSize--;
}
template<class T>
void chain<T>::insert(int theIndex, const T& theElement)
{
if (theIndex < 0 || theIndex > listSize)
{
ostringstream s("");
s << "index = " << theIndex << "size = " << listSize;
throw illegalIndex(s.str());
}
if (theIndex == 0)
firstNode = new chainNode<T>(theElement, firstNode);
else
{
chainNode<T>* p = firstNode;
for (int i = 0; i < theIndex - 1; i++)
p = p->next;
p->next = new chainNode<T>(theElement, p->next);
}
listSize++;
}
template<class T>
void chain<T>::output(ostream& out) const
{
for (chainNode<T>* currentNode = firstNode;
currentNode != nullptr;
currentNode = currentNode->next)
out << currentNode->element << " ";
}
template<class T>
ostream& operator<<(ostream& out, const chain<T>& x)
{
x.output(out);
return out;
}
template<class T>
void chain<T>::clear()
{
chainNode<T>* nextNode = nullptr;
while (firstNode != nullptr)
{
nextNode = firstNode->next;
delete firstNode;
firstNode = nextNode;
}
listSize = 0;
}
template<class T>
void chain<T>::push_back(const T& theElement)
{
chainNode<T>* newNode = new chainNode<T>(theElement, nullptr);
if (firstNode == nullptr)
firstNode = newNode;
else
{
chainNode<T>* currentNode = firstNode;
while (currentNode->next != nullptr)
currentNode = currentNode->next;
currentNode->next = newNode;
}
listSize++;
}
template<class T>
void chain<T>::setSize(int theSize)
{
if (listSize > theSize)
{
chainNode<T>* currentNode = firstNode;
for (int i = 0; i < theSize-1; i++)
currentNode = currentNode->next;
chainNode<T>* deleteNode = currentNode->next;
currentNode->next = nullptr;
while (deleteNode != nullptr)
{
currentNode = deleteNode->next;
delete deleteNode;
deleteNode = currentNode;
}
listSize = theSize;
}
}
template<class T>
void chain<T>::set(int theIndex, const T& theElement)
{
checkIndex(theIndex);
chainNode<T>* currentNode = firstNode;
for (int i = 0; i < theIndex - 1; i++)
currentNode = currentNode->next;
currentNode->element = theElement;
}
template<class T>
void chain<T>::removeRange(int fromIndex, int toIndex)
{
checkIndex(fromIndex+1);
checkIndex(toIndex-1);
chainNode<T>* fromNode = firstNode;
int i = 0;
for (i = 0; i < fromIndex; i++)
fromNode = fromNode->next;
chainNode<T>* toNode = fromNode->next;
i++;
chainNode<T>* deleteNode = nullptr;
while (i < toIndex)
{
deleteNode = toNode;
toNode = toNode->next;
delete deleteNode;
i++;
}
fromNode->next = toNode;
listSize = listSize - (toIndex - fromIndex - 1);
}
template<class T>
int chain<T>::lastIndexOf(const T& theElement)
{
int index = -1;
int loc = 0;
chainNode<T>* currentNode = firstNode;
while (currentNode != nullptr)
{
if (currentNode->element == theElement)
index = loc;
currentNode = currentNode->next;
loc++;
}
return index;
}
template<class T>
void chain<T>::swap(chain<T>& theChain)
{
chainNode<T>* temp = firstNode;
firstNode = theChain.firstNode;
theChain.firstNode = temp;
int tempnum = listSize;
listSize = theChain.listSize;
theChain.listSize = tempnum;
}
template<class T>
void chain<T>::toArray(arrayList<T>& theArray)
{
theArray.clear();
chainNode<T>* currentNode = firstNode;
for (int i = 0; i < listSize; i++)
{
theArray.push_back(currentNode->element);
currentNode = currentNode->next;
}
}
template<class T>
void chain<T>::leftShift(int i)
{
if (listSize > i)
{
chainNode<T>* deleteNode = nullptr;
for (int j = 0; j < i && j < listSize; j++)
{
deleteNode = firstNode;
firstNode = firstNode->next;
delete deleteNode;
}
listSize -= i;
}
else
throw illegalIndex();
}
template<class T>
void chain<T>::reverse()
{
chainNode<T>* beforeNode = nullptr;
chainNode<T>* currentNode = firstNode;
chainNode<T>* temp;
while (currentNode != nullptr)
{
temp = currentNode->next;
currentNode->next = beforeNode;
beforeNode = currentNode;
currentNode = temp;
}
firstNode = beforeNode;
}
template<class T>
void chain<T>::meld(chain<T>& a, chain<T>& b)
{
(*this).clear();
chainNode<T>* currentNode = nullptr;
while (a.firstNode != nullptr && b.firstNode != nullptr)
{
if (listSize == 0)
{
firstNode = a.firstNode;
a.firstNode = (a.firstNode)->next;
(a.listSize)--;
firstNode->next = b.firstNode;
b.firstNode = (b.firstNode)->next;
(b.listSize)--;
listSize += 2;
currentNode = firstNode->next;
}
else
{
currentNode->next = a.firstNode;
a.firstNode = (a.firstNode)->next;
(a.listSize)--;
listSize++;
currentNode = currentNode->next;
currentNode->next = b.firstNode;
b.firstNode = (b.firstNode)->next;
(b.listSize)--;
listSize++;
currentNode = currentNode->next;
}
}
if (a.firstNode != nullptr)
{
if (listSize == 0)
{
firstNode = a.firstNode;
a.firstNode = nullptr;
listSize += a.listSize;
a.listSize = 0;
}
else
{
currentNode->next = a.firstNode;
listSize += a.listSize;
a.firstNode = nullptr;
a.listSize = 0;
}
}
if (b.firstNode != nullptr)
{
if (listSize == 0)
{
firstNode = b.firstNode;
b.firstNode = nullptr;
listSize += b.listSize;
b.listSize = 0;
}
else
{
currentNode->next = b.firstNode;
b.firstNode = nullptr;
listSize+=b.listSize;
b.listSize = 0;
}
}
}
template<class T>
void chain<T>::merge(chain<T>& a, chain<T>& b)
{
(*this).clear();
chainNode<T>* currentNode = nullptr;
while (a.firstNode != nullptr && b.firstNode != nullptr)
{
if (listSize == 0)
{
if ((a.firstNode)->element <= (b.firstNode)->element)
{
firstNode = a.firstNode;
a.firstNode = (a.firstNode)->next;
listSize++;
a.listSize--;
currentNode = firstNode;
}
else
{
firstNode = b.firstNode;
b.firstNode = (b.firstNode)->next;
listSize++;
b.listSize--;
currentNode = firstNode;
}
}
else
{
if ((a.firstNode)->element <= (b.firstNode)->element)
{
currentNode->next = a.firstNode;
a.firstNode = (a.firstNode)->next;
listSize++;
a.listSize--;
currentNode = currentNode->next;
}
else
{
currentNode->next = b.firstNode;
b.firstNode = (b.firstNode)->next;
listSize++;
b.listSize--;
currentNode = currentNode->next;
}
}
}
if (a.firstNode != nullptr)
{
if (listSize == 0)
{
firstNode = a.firstNode;
a.firstNode = nullptr;
listSize += a.listSize;
a.listSize = 0;
}
else
{
currentNode->next = a.firstNode;
listSize += a.listSize;
a.firstNode = nullptr;
a.listSize = 0;
}
}
while (b.firstNode != nullptr)
{
if (listSize == 0)
{
firstNode = b.firstNode;
b.firstNode = nullptr;
listSize += b.listSize;
b.listSize = 0;
}
else
{
currentNode->next = b.firstNode;
b.firstNode = nullptr;
listSize += b.listSize;
b.listSize = 0;
}
}
}
template<class T>
void chain<T>::split(chain<T>& a, chain<T>& b)
{
chainNode<T>* currentNodeA = nullptr;
chainNode<T>* currentNodeB = nullptr;
for (int i = 0; i < listSize; i++)
{
if (i % 2 == 0)
{
if (b.listSize == 0)
{
b.firstNode = firstNode;
firstNode = firstNode->next;
(b.listSize)++;
currentNodeB = b.firstNode;
}
else
{
currentNodeB->next = firstNode;
firstNode = firstNode->next;
(b.listSize)++;
currentNodeB = currentNodeB->next;
}
}
else
{
if (a.listSize == 0)
{
a.firstNode = firstNode;
firstNode = firstNode->next;
(a.listSize)++;
currentNodeA = a.firstNode;
}
else
{
currentNodeA->next = firstNode;
firstNode = firstNode->next;
(a.listSize)++;
currentNodeA = currentNodeA->next;
}
}
}
listSize = 0;
currentNodeA->next = nullptr;
currentNodeB->next = nullptr;
}
template<class T>
void chain<T>::circularShift(int i)
{
chainNode<T>* originalNode = firstNode;
chainNode<T>* lastNode = nullptr;
for (int j = 0; j < i; j++)
{
firstNode = firstNode->next;
if (j == i - 2)
lastNode = firstNode;
}
chainNode<T>* currentNode = firstNode;
while (currentNode->next != nullptr)
currentNode = currentNode->next;
currentNode->next = originalNode;
lastNode->next = nullptr;
}
template<class T>
T& chain<T>::operator[](int i)
{
checkIndex(i);
chainNode<T>* currentNode = firstNode;
for (int j = 0; j < i; j++)
currentNode = currentNode->next;
return currentNode->element;
}
template<class T>
const T& chain<T>::operator[](int i) const
{
checkIndex(i);
chainNode<T>* currentNode = firstNode;
for (int j = 0; j < i; j++)
currentNode = currentNode->next;
return currentNode->element;
}
template<class T>
bool chain<T>::operator==(chain<T>& right) const
{
if (listSize == right.listSize)
{
int i = listSize;
chainNode<T>* leftNode = firstNode;
chainNode<T>* rightNode = right.firstNode;
while (i--)
{
if (leftNode->element != rightNode->element)
return false;
leftNode = leftNode->next;
rightNode = rightNode->next;
}
return true;
}
else
return false;
}
template<class T>
bool chain<T>::operator!=(chain<T>& right) const
{
if (listSize == right.listSize)
{
int i = listSize;
chainNode<T>* leftNode = firstNode;
chainNode<T>* rightNode = right.firstNode;
while (i--)
{
if (leftNode->element != rightNode->element)
return true;
leftNode = leftNode->next;
rightNode = rightNode->next;
}
return false;
}
else
return true;
}
template<class T>
bool chain<T>::operator<(chain<T>& right) const
{
if (listSize > right.listSize)
return false;
else
{
chainNode<T>* leftNode = firstNode;
chainNode<T>* rightNode = right.firstNode;
for (int i = 0; i < listSize; i++)
{
if (leftNode->element >= rightNode->element)
return false;
leftNode = leftNode->next;
rightNode = rightNode->next;
}
return true;
}
}
template<class T>
void chain<T>::bubbleSort()
{
for (int i = listSize; i > 1; i--)
{
int j = 1;
chainNode<T>* currentNode = firstNode;
while (j < i)
{
if (currentNode->element > currentNode->next->element)
Swap<T>(currentNode->element, currentNode->next->element);
currentNode = currentNode->next;
j++;
}
}
}
template<class T>
void chain<T>::rankSort()
{
int* r = new int[listSize];
for (int i = 0; i < listSize; i++)
r[i] = 0;
for (int i = listSize - 1; i >= 0; i--)
{
for (int j = 0; j < i; j++)
{
if ((*this)[i]>(*this)[j])
r[i]++;
else
r[j]++;
}
}
for (int i = 0; i < listSize; i++)
{
if (i != r[i])
{
Swap<T>((*this)[i], (*this)[r[i]]);
Swap<T>(r[i], r[r[i]]);
}
}
delete[] r;
}
template<class T>
T chain<T>::maxOfList()
{
chain<T>::iterator it = (*this).begin();
T tempMax = *it;
for (int i = 1; i < listSize; i++)
{
it++;
if ((*it) > tempMax)
{
tempMax = *it;
}
}
return tempMax;
}
template<class T>
void chain<T>::selectionSort()
{
int indexMax = 0;
bool is_sorted = false;
for (int i = listSize; i > 1 && !is_sorted; i--)
{
is_sorted = true;
indexMax = 0;
chain<T>::iterator it = (*this).begin();
T tempMax = *it;
for (int j = 1; j < i; j++)
{
it++;
if ((*it) > tempMax)
{
tempMax = *it;
indexMax = j;
}
else
is_sorted = false;
}
Swap<T>((*this)[i - 1], (*this)[indexMax]);
}
}
template<class T>
void chain<T>::insertSort()
{
for (int i = 1; i < listSize; i++)
{
chainNode<T>* currentNode = firstNode;
int tempData = (*this)[i];
int j = 0;
for (j = 0; j < i ; j++)
{
if (tempData < currentNode->element)
break;
else
currentNode = currentNode->next;
}
if (j != i)
{
(*this).insert(j, tempData);
(*this).erase(i + 1);
}
}
}
template<class T>
void chain<T>::binSort(int range)
{
chainNode<T>** bottom, ** top;
bottom = new chainNode<T>*[range + 1];
top = new chainNode<T>*[range + 1];
for (int b = 0; b <= range; b++)
bottom[b] = nullptr;
for (; firstNode != nullptr; firstNode = firstNode->next)
{
int data = firstNode->element;
if (bottom[data] == nullptr)
bottom[data] = top[data] = firstNode;
else
{
top[data]->next = firstNode;
top[data] = firstNode;
}
}
chainNode<T>* y = nullptr;
for (int bin = 0; bin <= range; bin++)
{
if (bottom[bin] != nullptr)
{
if (y == nullptr)
firstNode = bottom[bin];
else
y->next = bottom[bin];
y = top[bin];
}
}
if (y->next != nullptr)
y->next = nullptr;
delete[] bottom;
delete[] top;
}
template<class T>
void chain<T>::baseBinSort(int range)
{
chainNode<T>** bottom, ** top;
bottom = new chainNode<T>*[range + 1];
top = new chainNode<T>*[range + 1];
int maxData = maxOfList();
int binNum = 1;
while (maxData / (range + 1))
{
maxData /= (range + 1);
binNum++;
}
for(int i = 0;i< binNum;i++)
{
for (int b = 0; b <= range; b++)
bottom[b] = nullptr;
for (; firstNode != nullptr; firstNode = firstNode->next)
{
int data = int((firstNode->element)/pow(10,i)) % 10;
if (bottom[data] == nullptr)
bottom[data] = top[data] = firstNode;
else
{
top[data]->next = firstNode;
top[data] = firstNode;
}
}
chainNode<T>* y = nullptr;
for (int bin = 0; bin <= range; bin++)
{
if (bottom[bin] != nullptr)
{
if (y == nullptr)
firstNode = bottom[bin];
else
y->next = bottom[bin];
y = top[bin];
}
}
if (y->next != nullptr)
y->next = nullptr;
cout << "(*this) = " << *this << endl;
}
delete[] bottom;
delete[] top;
}
template<class T>
void meld(chain<T>& a, chain<T>& b, chain<T>& c)
{
c.clear();
typename chain<T>::iterator pointerA = a.begin();
typename chain<T>::iterator pointerB = b.begin();
while (pointerA != nullptr && pointerB != nullptr)
{
c.push_back(*pointerA);
pointerA++;
c.push_back(*pointerB);
pointerB++;
}
while (pointerA != nullptr)
{
c.push_back(*pointerA);
pointerA++;
}
while (pointerB != nullptr)
{
c.push_back(*pointerB);
pointerB++;
}
}
template<class T>
void merge(chain<T>& a, chain<T>& b, chain<T>& c)
{
c.clear();
typename chain<T>::iterator pointerA = a.begin();
typename chain<T>::iterator pointerB = b.begin();
while (pointerA != nullptr && pointerB != nullptr)
{
if (*pointerA > *pointerB)
{
c.push_back(*pointerB);
pointerB++;
}
else
{
c.push_back(*pointerA);
pointerA++;
}
}
while (pointerA != nullptr)
{
c.push_back(*pointerA);
pointerA++;
}
while (pointerB != nullptr)
{
c.push_back(*pointerB);
pointerB++;
}
}
template<class T>
void split(chain<T>& a, chain<T>& b, chain<T>& c)
{
a.clear();
b.clear();
typename chain<T>::iterator pointerC = c.begin();
for (int i = 0; i < c.size(); i++)
{
if (i % 2 == 1)
{
a.push_back(*pointerC);
pointerC++;
}
else
{
b.push_back(*pointerC);
pointerC++;
}
}
}
#endif
_7arrayAndChain.h
#pragma once
#ifndef _ARRAYANDCHAIN_H_
#define _ARRAYANDCHAIN_H_
#include "_6chain.h"
#include "_5arrayList.h"
template<class T>
chain<T> arrayToChain(const arrayList<T>& arrayTo)
{
chain<T> toChain;
int size = arrayTo.size();
T data = 0;
for (int i = 0; i < size; i++)
{
data = arrayTo.get(i);
toChain.insert(i, data);
}
return toChain;
}
template<class T>
arrayList<T> chainToArray(const chain<T>& chainTo)
{
arrayList<T> toArray;
int size = chainTo.size();
T data = 0;
for (int i = 0; i < size; i++)
{
data = chainTo.get(i);
toArray.insert(i, data);
}
return toArray;
}
#endif
_1main.cpp
#include <iostream>
#include "_6chain.h"
int main()
{
chainTest();
return 0;
}
_6chain.cpp
#include "_5arrayList.h"
#include "_6chain.h"
#include "_7arrayAndChain.h"
using std::cout;
using std::endl;
void chainTest()
{
cout << endl << "**********************************chainTest()函数开始*****************************************" << endl;
cout << "测试成员函数*********************************************" << endl;
cout << "测试构造函数******************" << endl;
chain<int> data;
cout << "测试insert()成员函数**********" << endl;
data.insert(0, 99);
data.insert(0, 88);
data.insert(0, 77);
data.insert(0, 66);
cout << "测试输出**********************" << endl;
cout << "data = " << data << endl;
cout << "测试复制构造函数**************" << endl;
chain<int> data1(data);
cout << "data1 = " << data1 << endl;
cout << "测试使用arrayList初始化链表的构造函数" << endl;
arrayList<int> arrayData2;
arrayData2.push_back(1);
arrayData2.push_back(2);
arrayData2.push_back(3);
chain<int> chainData1(arrayData2);
cout << "chainData1 = " << chainData1 << endl;
cout << "测试get()成员函数*************" << endl;
cout << "data.get(0) = " << data.get(0) << endl;
cout << "测试indexOf()成员函数*********" << endl;
cout << "data.indexOf(99) = " << data.indexOf(99) << endl;
cout << "测试erase()成员函数***********" << endl;
data.erase(0);
cout << "data = " << data << endl;
cout << "测试clear()成员函数***********" << endl;
data1.clear();
cout << "data1 = " << data1 << endl;
cout << "测试push_back()成员函数*******" << endl;
data1.push_back(99);
cout << "data1 = " << data1 << endl;
data.push_back(66);
cout << "data = " << data << endl;
cout << "测试setSize()成员函数*********" << endl;
data.setSize(5);
cout << "data = " << data << endl;
data.setSize(3);
cout << "data = " << data << endl;
data.setSize(2);
cout << "data = " << data << endl;
cout << "测试set()成员函数*************" << endl;
data.insert(0, 5);
data.insert(0, 9);
data.insert(0, 8);
data.insert(0, 2);
cout << "data = " << data << endl;
data.set(0, 99);
cout << "data = " << data << endl;
cout << "测试removeRange()成员函数*****" << endl;
data.removeRange(1, 3);
cout << "data = " << data << endl;
cout << "测试lastIndexOf()成员函数*****" << endl;
cout << "data.lastIndexOf(8) = " << data.lastIndexOf(8) << endl;
cout << "data.lastIndexOf(2) = " << data.lastIndexOf(2) << endl;
cout << "测试swap()成员函数************" << endl;
chain<int> data3(data1);
chain<int> data4(data);
cout << "data3 = " << data3 << endl;
cout << "data4 = " << data4 << endl;
data3.swap(data4);
cout << "data3 = " << data3 << endl;
cout << "data4 = " << data4 << endl;
cout << "测试toArray()成员函数*********" << endl;
arrayList<int> arrayData3;
cout << "arrayData3 = " << arrayData3 << endl;
data3.toArray(arrayData3);
cout << "arrayData3 = " << arrayData3 << endl;
cout << "测试leftShift()成员函数*********" << endl;
cout << "data3 = " << data3 << endl;
data3.leftShift(2);
cout << "data3 = " << data3 << endl;
cout << "测试reverse()成员函数***********" << endl;
data3.push_back(10);
data3.push_back(66);
cout << "data3 = " << data3 << endl;
data3.reverse();
cout << "data3 = " << data3 << endl;
cout << "测试meld()成员函数**************" << endl;
data4.push_back(68);
chain<int> data5;
chain<int> data6(data3);
chain<int> data7(data4);
chain<int> data8(data3);
cout << "data3 = " << data3 << endl;
cout << "data4 = " << data4 << endl;
data5.meld(data3, data4);
cout << "data5.meld(data3, data4)之后**" << endl;
cout << "data3 = " << data3 << endl;
cout << "data4 = " << data4 << endl;
cout << "data5 = " << data5 << endl << endl;
cout << "data7 = " << data7 << endl;
cout << "data6 = " << data6 << endl;
data5.meld(data7, data6);
cout << "data5.meld(data7, data6)之后**" << endl;
cout << "data7 = " << data7 << endl;
cout << "data6 = " << data6 << endl;
cout << "data5 = " << data5 << endl << endl;
chain<int> data9;
cout << "data8 = " << data8 << endl;
cout << "data9 = " << data9 << endl;
data5.meld(data8, data9);
cout << "data5.meld(data8, data9)之后**" << endl;
cout << "data8 = " << data8 << endl;
cout << "data8.size() = " << data8.size() << endl;
cout << "data9 = " << data9 << endl;
cout << "data9.size() = " << data9.size() << endl;
cout << "data5 = " << data5 << endl;
cout << "data5.size() = " << data5.size() << endl;
cout << "测试merge()成员函数*************" << endl;
chain<int> data10(data5);
data10.erase(0);
chain<int> data11;
cout << "data5 = " << data5 << endl;
cout << "data10 = " << data10 << endl;
cout << "data11 = " << data11 << endl;
data11.merge(data5, data10);
cout << "data11.merge(data5, data10)之后" << endl;
cout << "data5 = " << data5 << endl;
cout << "data5.size() = " << data5.size() << endl;
cout << "data10 = " << data10 << endl;
cout << "data10.size() = " << data10.size() << endl;
cout << "data11 = " << data11 << endl;
cout << "data11.size() = " << data11.size() << endl;
cout << "测试split()成员函数*************" << endl;
cout << "测试circularShift()成员函数*****" << endl;
data11.split(data5, data10);
cout << "data5 = " << data5 << endl;
cout << "data5.size() = " << data5.size() << endl;
cout << "data10 = " << data10 << endl;
cout << "data10.size() = " << data10.size() << endl;
cout << "data11 = " << data11 << endl;
cout << "data11.size() = " << data11.size() << endl;
cout << "测试circularShift()成员函数*****" << endl;
data5.circularShift(2);
cout << "data5 = " << data5 << endl;
cout << endl << "重载操作符************************************************" << endl;
cout << "测试[]操作符******************" << endl;
cout << "data = " << data << endl;
cout << "data[0] = " << data[0] << endl;
cout << "data[1] = " << data[1] << endl;
cout << "data[2] = " << data[2] << endl;
data[0] = 88;
cout << "data = " << data << endl;
cout << "测试==操作符******************" << endl;
chain<int> data2(data);
cout << "data2 = " << data2 << endl;
cout << "data = " << data << endl;
cout << "data1 = " << data1 << endl;
cout << "(data2 == data) = " << (data2 == data) << endl;
cout << "(data2 == data1) = " << (data2 == data1) << endl;
data2[4] = 9;
cout << "data2 = " << data2 << endl;
cout << "data = " << data << endl;
cout << "(data2 == data) = " << (data2 == data) << endl;
cout << "测试!=操作符******************" << endl;
cout << "data2 = " << data2 << endl;
cout << "data = " << data << endl;
cout << "data1 = " << data1 << endl;
cout << "(data2 != data) = " << (data2 != data) << endl;
cout << "(data2 != data1) = " << (data2 != data1) << endl;
data2[4] = 88;
cout << "data2 = " << data2 << endl;
cout << "data = " << data << endl;
cout << "(data2 != data) = " << (data2 != data) << endl;
cout << "测试<操作符*******************" << endl;
cout << "data2 = " << data2 << endl;
cout << "data = " << data << endl;
data1[0] = 66;
cout << "data1 = " << data1 << endl;
cout << "(data2 < data) = " << (data2 < data) << endl;
cout << "(data1 < data2) = " << (data1 < data2) << endl;
data2[0] = 1;
data2[1] = 1;
data2[2] = 1;
data2[3] = 1;
data2[4] = 1;
cout << "data2 = " << data2 << endl;
cout << "data = " << data << endl;
cout << "(data2 < data) = " << (data2 < data) << endl;
cout << endl << "测试非成员函数******************************************" << endl;
arrayList<int> arrayData;
arrayData.push_back(9);
arrayData.push_back(999);
arrayData.push_back(99);
cout << "测试arrayToChain()函数********" << endl;
cout << "arrayData = " << arrayData << endl;
chain<int> chainData(arrayToChain(arrayData));
cout << "chainData = " << chainData << endl;
cout << "测试chainToArray()函数********" << endl;
arrayList<int> arrayData1(chainToArray(chainData));
arrayData1.push_back(88);
cout << "arrayData1 = " << arrayData1 << endl;
cout << "测试meld()函数****************" << endl;
chain<int> chainData3(arrayToChain(arrayData));
chain<int> chainData4;
cout << "chainData = " << chainData << endl;
cout << "chainData3 = " << chainData3 << endl;
meld(chainData, chainData3, chainData4);
cout << "chainData4 = " << chainData4 << endl << endl;
chainData3.insert(0, 68);
chainData3.insert(0, 98);
cout << "chainData = " << chainData << endl;
cout << "chainData3 = " << chainData3 << endl;
meld(chainData, chainData3, chainData4);
cout << "chainData4 = " << chainData4 << endl<<endl;
meld(chainData3, chainData, chainData4);
cout << "chainData4 = " << chainData4 << endl<<endl;
chain<int> chainData5;
meld(chainData3, chainData5, chainData4);
cout << "chainData3 = " << chainData3 << endl;
cout << "chainData5 = " << chainData5 << endl;
cout << "chainData4 = " << chainData4 << endl << endl;
meld(chainData5, chainData3, chainData4);
cout << "chainData5 = " << chainData5 << endl;
cout << "chainData3 = " << chainData3 << endl;
cout << "chainData4 = " << chainData4 << endl << endl;
cout << "测试split()函数**************" << endl;
chain<int> chainData6;
chain<int> chainData7;
cout << "chainData6 = " << chainData6 << endl;
cout << "chainData7 = " << chainData7 << endl;
cout << "chainData4 = " << chainData4 << endl;
split(chainData6, chainData7, chainData4);
cout << "split(chainData6, chainData7, chainData4)之后" << endl;
cout << "chainData6 = " << chainData6 << endl;
cout << "chainData6.size() = " << chainData6.size() << endl;
cout << "chainData7 = " << chainData7 << endl;
cout << "chainData7.size() = " << chainData7.size() << endl;
cout << "chainData4 = " << chainData4 << endl;
cout << "chainData4.size() = " << chainData4.size() << endl;
cout << endl << "排序****************************************************" << endl;
cout << "测试bubbleSort()成员函数********" << endl;
data5.bubbleSort();
cout << "data5 = " << data5 << endl;
cout << "测试rankSort()成员函数**********" << endl;
data5.reverse();
cout << "data5 = " << data5 << endl;
data5.rankSort();
cout << "data5 = " << data5 << endl;
cout << "maxOfList()*******************************" << endl;
cout << "data5.maxOfList() = " << data5.maxOfList() << endl;
cout << "selectionSort()排序***********************" << endl;
data5.reverse();
cout << "data5 = " << data5 << endl;
data5.selectionSort();
cout << "data5 = " << data5 << endl;
cout << "insertSort()排序**************************" << endl;
data5.reverse();
data5.insert(1, 99);
cout << "data5 = " << data5 << endl;
data5.insertSort();
cout << "data5 = " << data5 << endl;
cout << "binSort()排序****************************" << endl;
chain<int> data12;
data12.push_back(0);
data12.push_back(5);
data12.push_back(3);
data12.push_back(4);
data12.push_back(2);
data12.push_back(5);
cout << "data12 = " << data12 << endl;
data12.binSort(5);
cout << "data12 = " << data12 << endl;
cout << "baseBinSort()排序************************" << endl;
chain<int> data13;
data13.push_back(216);
data13.push_back(521);
data13.push_back(425);
data13.push_back(116);
data13.push_back(91);
data13.push_back(515);
data13.push_back(124);
data13.push_back(34);
data13.push_back(96);
data13.push_back(24);
cout << "data13 = " << data13 << endl;
data13.baseBinSort(9);
cout << "data13 = " << data13 << endl;
cout << endl << "友元函数***********************************************************************" << endl;
cout << "cin>>*************************************" << endl;
chain<int> cindata;
cin >> cindata;
cout << "cindata = " << cindata << endl;
cout << "**********************************chainTest()函数结束*****************************************" << endl;
}
|