数据结构——线性表(顺序表)

242 阅读3分钟

线性表是一种最基本、最简单的数据结构,数据元素之间仅具有单一的前驱和后继关系。

顺序表

① 采用静态分配方式

采用C++的模板机制定义模板类SeqList。

const int MaxSize = 100;		// 根据实际问题具体定义
template<typename DataType>		// 定义模板类SeqList 
class SeqList{
	public:
		SeqList();			// 建立空的顺序表
		SeqList(DataType a[],int n);	// 建立长度为n的顺序表
		~SeqList(){} 			// 析构函数
		int Length();			// 求线性表的长度
		DataType Get(int i);		// 按位查找,查找第i个元素的值
		int Locate(DataType x);		// 按值查找,查找值为x的元素序号
		void Insert(int i,DataType x);	// 插入操作,在第i个位置插入值为x的元素
		DataType Delete(int i);		// 删除操作,删除第i个元素
		bool Empty();			// 判断线性表是否为空
		void PrintList();		// 遍历操作,按序号依次输出各元素 
	private:
		DataType data[MaxSize];	        // 存放数据元素的数组
		int length;			// 线性表的长度 
};

1.无参构造函数

template<typename DataType>
SeqList<DataType>::SeqList(){
    length = 0;
}

2.有参构造函数

template<typename DataType>
SeqList<DataType>::SeqList(DataType a[],int n){
    if (n > MaxSize)
        throw "illegal parameter";
    for (int i=0; i<n; i++)
        data[i] = a[i];
    length = n;
}

3.判空操作

template<typename DataType>
bool SeqList<DataType>::Empty(){
    return length==0?true:false;
}

4.求顺序表的长度

template<typename DataType>
int SeqList<DataType>::Length(){
    return length;
}

5.遍历操作

template<typename DataType>
void SeqList<DataType>::PrintList(){
    for (int i=0; i<length; i++){
        cout << data[i] << "\t";
    }
    cout << endl;
}

6.按位查找 O(1)

template<typename DataType>
DataType SeqList<DataType>::Get(int i){
    // 按位查找,时间复杂度为O(1)
    if (i<1 || i>length)
    	throw "illegal search location";
    else
    	return data[i-1]; 
}

7.按值查找 O(n)

template<typename DataType>
int SeqList<DataType>::Locate(DataType x){
    // 按值查找,时间复杂度为O(n) 
    for (int i=0; i<length; i++){
    	if (data[i]==x)
            return i+1;
    }

    return -1;		// 退出循环,说明查找失败 
}

8.插入操作 O(n)

template<typename DataType>
void SeqList<DataType>::Insert(int i,DataType x){
    // 插入操作,时间复杂度为O(n)
    if (length==MaxSize)
    	throw "overflow";
    if (i<1 || i>length+1)
    	throw "illegal insertion location";
    for (int j=length; j>=i; j--){
        data[j] = data[j-1];		// 将待插入位置右侧的元素向右移动 
    }
    data[i-1] = x;
    length++;
}

9.删除操作 O(n)

template<typename DataType>
DataType SeqList<DataType>::Delete(int i){
    // 删除操作,时间复杂度为O(n) 
    DataType x;
    if (length == 0)
    	throw "underflow";
    if (i<1 || i>length)
        throw "illegal deleted location";
    x = data[i-1];
    for (int j=i; j<length; j++){
        data[j-1] = data[j];	// 将待删除元素的右侧元素向左移动
    }
    length--;

    return x; 
}

② 采用动态分配方式

采用C++的模板机制定义模板类SeqList。

const int InitSize = 100;		// 顺序表的初始长度
const int IncreSize = 10;		// 顺序表存储空间每次扩展的长度 
template<typename DataType>		// 定义模板类SeqList 
class SeqList{
	public:
		// 与顺序表的静态分配相同 
		SeqList();			// 建立空的顺序表
		SeqList(DataType a[],int n);	// 建立长度为n的顺序表
		~SeqList();			// 析构函数
		int Length();			// 求线性表的长度
		DataType Get(int i);		// 按位查找,查找第i个元素的值
		int Locate(DataType x);		// 按值查找,查找值为x的元素序号
		void Insert(int i,DataType x);	// 插入操作,在第i个位置插入值为x的元素
		DataType Delete(int i);		// 删除操作,删除第i个元素
		bool Empty();			// 判断线性表是否为空
		void PrintList();		// 遍历操作,按序号依次输出各元素 
	private:
		DataType *data;		// 动态申请数组空间的首地址
		int maxSize;		// 当前数组空间的最大长度
		int length;		// 线性表的长度 
};

在顺序表的动态分配方式下,求线性表的长度、按位查找、按值查找、删除、判空和遍历等基本操作的算法,与顺序表的静态分配方式相同。下面讨论其他基本操作的实现。

1.无参构造函数

template<typename DataType>
SeqList<DataType>::SeqList(){
    data = new DataType[InitSize];
    maxSize = InitSize; 
    length = 0;
}

2.有参构造函数

template<typename DataType>
SeqList<DataType>::SeqList(DataType a[],int n){
    data = new DataType[2*n];
    maxSize = 2*n;
    for (int i=0; i<n; i++){
    	data[i] = a[i];
    }
    length = n;
}

3.析构函数

template<typename DataType>
SeqList<DataType>::~SeqList(){
    delete[] data;
}

4.插入操作 O(n)

template<typename DataType>
void SeqList<DataType>::Insert(int i,DataType x){
    if (i<1 || i>length+1)
    	throw "illegal insertion location";
    if (length == maxSize){
    	// 发生上溢,扩充存储空间
    	DataType *oldData = data;
    	maxSize += IncreSize;
    	data = new DataType[maxSize];
    	for (int j=0; j<length; j++){
      	    data[j] = oldData[j];
        }
        delete[] oldData;
    }

    for (int j=length; j>=i; j--){
        data[j] = data[j-1];
    }
    data[i-1] = x;
    length++;
}