In computer science, a list or sequence is an abstract data type that implements a finite ordered collection of values, where the same value may occur more than once. An instance of a list is a computer representation of the mathematical concept of a finite sequence; the (potentially) infinite analog of a list is astream. Lists are a basic example of containers, as they contain other values. If the same value occurs multiple times, each occurrence is considered a distinct item. Lists are distinguished from arrays in that lists only allow sequential access, while arrays allow random access.
The name list is also used for several concrete data structures that can be used to implement abstract lists, especiallylinked lists.
- 创建一个线性表
- 确定线性表是否为空
- 确定线性表的长度
- 查找第k个元素
- 查找指定的元素
- 在第k个元素之后插入一个新元素
#ifndef LIST_H
#define LIST_H
#include<iostream>
using namespace std;
//定义list.h中的内容,即为数组表示的线性表。
//基于公式的类LinearList
template<class T>
class LinearList{
public:
LinearList(int MaxListSize = 10);//构造函数
~LinearList() {delete [] element;}//析构函数
bool IsEmpty() const {return length == 0;}
int Length() const {return length;}
bool Find(int k,T& x) const;//返回第k个元素至x中
int Search(const T& x) const;//返回x所在的位置
LinearList<T>& Delete(int k,T& x);//删除第k个元素并将它返回至x中
LinearList<T>& Insert(int k,const T&x);//在第k个元素之后插入x
void Output(ostream& out) const;
private:
int length;
int MaxSize;
T *element;//一维动态数组
};
//基本的表操作如下
template<class T>
LinearList<T>::LinearList(int MaxListSize){
//基于公式的线性表的构造函数
MaxSize = MaxListSize;
element = new T[MaxSize];
length=0;
}
template<class T>
bool LinearList<T>::Find(int k,T& x) const{
//把第k个元素取至x中
//如果不存在第k个元素则返回false,否则返回true
if(k<1||k>length) return false;//不存在第k个元素
x=element[k-1];
return true;
}
template<class T>
int LinearList<T>::Search(const T& x) const{
//查找x,如果找到,则返回x所在的位置
//如果x不在表中,则返回0
for(int i=0;i<length;i++)
if(element[i]==x) return +++i;
return 0;
}
template<class T>
LinearList<T>& LinearList<T>::Delete(int k, T& x){
//把第k个元素放入x中,然后删除第k个元素
//如果不存在第k个元素,则引发异常OutOfBounds
if (Find(k, x)){//把元素k+1,...向前移动一个位置
for (int i = k; i < length; i++)
element[i - 1] = element[i];
length--;
return *this;
}
else throw OutOfBounds();
}
template<class T>
LinearList<T>& LinearList<T>::Insert(int k, const T& x){
//在第k个元素之后插入x
//如果不存在第k个元素,则引发异常OutOfBounds
//如果表已经满,则引发异常NoMem();
if (k<0 || k>length) throw OutOfBounds();
if (length == MaxSize) throw NoMem();
//插入元素,并将后面元素向后移动一位
for (int i = length-1; i >k&&i==k; i++)
element[i + 1] = element[i];
element[k] = x;
length++;
return *this;
}
template<class T>
void LinearList<T>::Output(ostream& out) const{
//把表送至输出流
for (int i = 0; i < length; i++)
out << element[i] << " ";
}
//重载操作符<<
template<class T>
ostream& operator<<(ostream& out, const LinearList<T>& x){
x.Output(out);
return out;
}
class OutOfBounds{
public:
OutOfBounds() {}
};
//内存不足
//自己引发的异常NoMem
class NoMem{
public:
NoMem(){}
};
//使new引发NoMem异常而不是xalloc异常
void my_new_handler(){
throw NoMem();
}
new_handler Old_Handler_ =set_new_handler(my_new_handler);//调用函数set_new_handler,每当分配内存失败时,该函数就让操作符new调用函数my_new_handler()
#endif
#include<iostream>
#include"list.h"
#include<conio.h>
using namespace std;
void main(void){
try{
LinearList<int>L(5);
cout << "Length = " << L.Length() << endl;
cout << "IsEmpty = " << L.IsEmpty() << endl;
L.Insert(0, 2).Insert(1, 6);
cout << "List is " << L << endl;
cout << "IsEmpty = " << L.IsEmpty() << endl;
int z;
L.Find(1, z);
cout << "First element is " << z << endl;
cout << "Length = " << L.Length() << endl;
L.Delete(1, z);
cout << "Delete element is " << z << endl;
cout << "List is " << L << endl;
}
catch (NoMem){
cerr << "An exception has occurred" << endl;
}
}
运行结果截图如下:
但是,在接受一个线性表的公式化描述方法之前,先来考察一下这种描述方法的优缺点。的确,对于一个线性表的各种操作可以用非常简单的c++函数来实现。执行查找、删除和修改的函数都有一个最差的、与表的大小呈线性关系的时间复杂性。我们可能满足于这种复杂性。