数据结构(3)——线性表,最简单的数据结构

来源:互联网 发布:js数组移除一个元素 编辑:程序博客网 时间:2024/05/22 13:14

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.

A singly linked list structure, implementing a list with 3 integer elements.

The name list is also used for several concrete data structures that can be used to implement abstract lists, especiallylinked lists.

摘录自维基百科,线性表List (abstract data type).
可见,线性表虽然简单,但它却是很多派生数据结构的基础(如右图,可以拓展成链表),而且还是a basic example of containers.正好练习c++,而且大一已经学过c语言的表示方法,再使用c语言表示除了复习一下以外也没什么意义,所以重新用c++表示并做测试,既复习也巩固练习c++.
首先,先实现最简单的、由数组表示的一个线性表对象实例,将得到的代码放入list.h这个头文件,方便进行后续的测试。
注意,这里实现的是一个线性表,而线性表和链表是有区别的。线性表示数据结构中最简单的一种数据结构,它是顺序存储的,通过数组实现;而链表在内存中是离散存储的,通过指针实现。对于一个线性表,我们有必要实现以下操作:
  • 创建一个线性表
  • 确定线性表是否为空
  • 确定线性表的长度
  • 查找第k个元素
  • 查找指定的元素
  • 在第k个元素之后插入一个新元素
#ifndef  LIST_H#define LIST_H#include<iostream>using namespace std;//定义list.h中的内容,即为数组表示的线性表。//基于公式的类LinearListtemplate<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个元素之后插入xvoid 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,否则返回trueif(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不在表中,则返回0for(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个元素,则引发异常OutOfBoundsif (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() {}};//内存不足//自己引发的异常NoMemclass 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

接着,就可以写测试代码来对list.h进行测试(这并不是难点):
#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++函数来实现。执行查找、删除和修改的函数都有一个最差的、与表的大小呈线性关系的时间复杂性。我们可能满足于这种复杂性。
这种描述方法的一大缺点就是空间的低效利用。如果我们需要三个表,而且知道三个表的总元素不超过5000个,但是有可能某个时刻某个表需要5000个元素,而另一时刻另一个表也需要5000个元素,这样就必须保证每个表的容量都是5000个元素,然后又必然有很多元素是空的。
于是,链表诞生了。

0 0
原创粉丝点击