c++基于顺序表和链表的线性表物理实现
一、 线性表物理实现的整体理解:
1、线性表的定义和声明是用模板类来实现的。这个部分是一个抽象数据类型定义,模板类是一个接口,就是你在里边把你想要实现的功能函数名称都写进去,相当于是一个你的设想。
2、然后那个E类型也是一个抽象类型,它能代表很多东西,因为你事先不知道你想要用这个对列来存取整型还是字符串还是别的什么,所以先用这个代替。
3、接着线性表的物理实现用一个类来继承模板类,把模板类具体的操作实现出来。相当于是把之前的设想细化,变为具体操作。
4、最后demo程序d就是在主函数里边把你写的线性表中的函数都调用一下,测试看看写的函数对不对。主要起到一个测试功能。
二、 基于顺序表和链表实现线性表的对比:
在空间上:
1、 空间分配:基于数组实现线性表需要预先分配,基于链表实现线性表需要按需分配。
2、 空间利用:基于数组实现线性表会造成空间浪费,基于链表实现线性表会造成结构性开销。
在时间上:
1、 引用型操作:基于数组实现线性表时间开销为O(1),基于链表实现线性表时间开销为O(n)。
2、 加工型操作:基于数组实现线性表时间开销为O(n),基于链表实现线性表时间开销为O(1)。
在编程语言和软件工程上:
1、 编程语言:编程语言支持基于数组实现线性表,部分支持基于链表实现线性表。
2、 软件工程:基于数组实现线性表简单易用,基于链表实现线性表操作负责。
基于顺序表实现线性表
线性表的声明和定义:
(抽象定义时的功能可以根据自己的需要选择定义,但最好定义的全一些,这样在实现和使用的时候才不会想到什么再补上什么)
#ifndef LIST_H
#define LIST_H
template<typename E> class List { // List ADT 抽象数据类型定义
private:
void operator =(const List&) {} // Protect assignment
List(const List&) {} // Protect copy constructor
public:
List() {} // Default constructor 构造函数
virtual ~List() {} // Basedestructor 析构函数
// Clear contents from thelist, to make it empty. 清空列表中的内容
virtual void clear() = 0;
// Insert an element at the current location.
// item: The element to be inserted 在当前位置插入元素item
virtual void insert(const E& item) = 0;
// Append an element at the end of the list.
// item: The element to be appended 在表尾添加元素item
virtual void append(const E& item) = 0;
// Remove and return the current element.
// Return: the element that was removed. 删除当前元素,并将其作为返回值
virtual E remove() = 0;
// Set the current position to the start of the list. 将当前位置设置为顺序表起始处
virtual void moveToStart() = 0;
// Set the current position to the end of the list. 将当前位置设置为顺序表末尾
virtual void moveToEnd() = 0;
// Move the current position one step left. No change
// if already at beginning. 将当前位置左移一步,如果当前位置在首位就不变
virtual void prev() = 0;
// Move the current position one step right. No change
// if already at end. 将当前位置右移一步,如果当前位置在末尾就不变
virtual void next() = 0;
// Return: The number of elements in the list. 返回列表当前的元素个数
virtual int length() const = 0;
// Return: The position of the current element. 返回当前元素的位置
virtual int currPos() const = 0;
// Set current position.
// pos: The position to make current. 将当前位置设置为pos
virtual void moveToPos(int pos) = 0;
// Return: The current element. 返回当前元素
virtual const E& getValue() const = 0;
};
#endif
线性表物理实现部分:
#include"list.h"
#include<assert.h>
template<typename E> // Array-based list implementation 基于数组的线性表实现
class Mylist : public List<E> {
private:
int maxSize; // Maximum size of list 顺序表的容量
int listSize; // Number of list items now 目前的大小
int curr; // Position of current element 当前元素的位置
E* listArray; // Array holding list elements 列表元素将存放到该数组中
public:
Mylist(int size=100) { // Constructor 构造函数
maxSize = size;
listSize = curr = 0;
listArray = new E[maxSize];
}
~Mylist() { delete [] listArray; } // Destructor 析构函数
void clear() { // Reinitialize the list 初始化顺序表
delete [] listArray; // Remove the array 删除原有数组
listSize = curr = 0; // Reset the size 重新设置列表参数
listArray = new E[maxSize]; // Recreate array 新建空数组
}
// Insert "it" atcurrent position 在当前位置插入it
void insert(const E& it) {
assert(listSize < maxSize); //"List capacity exceeded"超出顺序表范围会断言终止程序
for(int i=listSize; i>curr; i--) // Shift elements up 右移元素
listArray[i] = listArray[i-1]; // to make room
listArray[curr] = it;
listSize++; //Increment list size 列表长度加一
}
void append(const E& it) { // Append "it" 在顺序表的末尾追加it
assert(listSize < maxSize); // 断言判断
listArray[listSize++] = it;
}
// Remove and return thecurrent element. 删除并返回当前元素
E remove() {
assert((curr>=0) && (curr <listSize)); // No element 没有元素会断言终止程序
E it = listArray[curr]; // Copy the element 拷贝当前元素
for(int i=curr; i<listSize-1; i++) // Shift them down 左移元素
//listArray[curr]将被覆盖掉
listArray[i] = listArray[i+1];
listSize--; // Decrementsize 列表长度减一
return it;
}
void moveToStart() { curr = 0; } // Reset position. 将curr当前位置设置为开头
void moveToEnd() { curr = listSize; } // Set at end . 将curr设置为末尾
void prev() { if (curr != 0) curr--; } // Back up. 将curr前移一位
void next() { if (curr < listSize) curr++;} // Next. 将curr后移一位
// Return list size 返回顺序表长度
int length() const { return listSize; }
// Return current position 返回当前位置
int currPos() const { return curr; }
// Set current list position to "pos" 将当前位置curr设置为pos
void moveToPos(int pos) {
assert ((pos>=0)&&(pos<=listSize)); // Pos out of range
//pos超出顺序表范围会断言终止程序
curr = pos;
}
const E& getValue() const { // Returncurrent element 返回值是当前元素
assert((curr>=0)&&(curr<listSize)); //No current element
//当前位置超出范围时断言终止程序
return listArray[curr];
}
};
demo:
#include <iostream>
#include"List.h"
#include"Mylist.cpp"
#include<stdlib.h>
using namespace std;
int main(int argc, char** argv) {
Mylist<int> array(20);
int n,i;
cout<<"基于顺序表实现线性表的基本操作如下:"<<endl<<endl;
cout<<"1.向顺序表中添加10个100以内的随机数元素"<<endl;
for(i=0;i<10;i++)
array.append(rand()%(100-1+1)+1);
cout<<"顺序表当前所有元素为:";
for(i=0;i<array.length();i++){
array.moveToPos(i);
cout<<array.getValue()<<' ';
}
cout<<endl<<endl;
cout<<"2.将当前位置设置成3"<<endl;
array.moveToPos(3);
cout<<"当前位置为:"<<array.currPos()<<endl<<endl;
cout<<"3.删除当前位置元素"<<endl;
array.remove();
cout<<"顺序表当前所有元素为:";
for(i=0;i<array.length();i++){
array.moveToPos(i);
cout<<array.getValue()<<' ';
}
cout<<endl<<endl;
cout<<"4.计算当前元素个数:";
cout<<"当前元素个数为:"<<array.length()<<endl<<endl;
cout<<"5.在当前位置插入元素5"<<endl;
array.insert(5);
cout<<"顺序表当前所有元素为:";
for(i=0;i<array.length();i++){
array.moveToPos(i);
cout<<array.getValue()<<' ';
}
return 0;
}
基于链表实现线性表
线性表的声明和定义:
#ifndef LIST
#define LIST
template <typename E> class List { // List ADT 抽象数据类型定义
private:
void operator=(const List&) {} // Protect assignment
List(const List&) {} // Protect copy constructor
public:
List() {} // Default constructor 构造函数
virtual~List() {} // Base destructor 析构函数
// Clear contents from the list, to make itempty. 清空列表中的内容
virtual void clear() = 0;
// Insert an element at the current location.
// item: The element to be inserted 在当前位置插入元素item
virtual void insert(const E& item) = 0;
// Append an element at the end of the list.
// item: The element to be appended 在表尾添加元素item
virtual void append(const E& item) = 0;
// Remove and return the current element.
// Return: the element that was removed. 删除当前元素,并将其作为返回值
virtual E remove() = 0;
// Set the current position to the start ofthe list.将当前位置设置为顺序表起始处
virtual void moveToStart() = 0;
// Set the current position to the end of thelist. 将当前位置设置为顺序表末尾
virtual void moveToEnd() = 0;
// Move the current position one step left.No change
// if already at beginning. 将当前位置左移一步,如果当前位置在首位就不变
virtual void prev() = 0;
// Move the current position one step right.No change
// if already at end. 将当前位置右移一步,如果当前位置在末尾就不变
virtual void next()= 0;
// Return: The number of elements in thelist. 返回列表当前的元素个数
virtual int length() const = 0;
// Return: The position of the currentelement. 返回当前元素的位置
virtual int currPos() const = 0;
// Set current position.
// pos: The position to make current. 将当前位置设置为pos
virtual void moveToPos(int pos) = 0;
// Return: The current element. 返回当前元素
virtual const E& getValue() const = 0;
};
#endif
#include <iostream>
template <typename E> class Link {
public:
E element; // Value forthis node 结点值
Link*next; // Pointer to next node in list 结点指针:在链表中指向下一结点
// Constructors 构造函数
Link(const E& elemval, Link* nextval =NULL){
element =elemval;
next = nextval;
}
Link(Link*nextval =NULL){
next = nextval;
}
};
线性表的物理实现
#include "list.h"
#include<assert.h>
//This is the declaration for LList. It is split into two parts
//because it is too big to fit on one book page
//Linked list implementation
using namespace std;
template <typename E> class Mylist:public List<E> {
private:
Link<E>* head; // Pointer to list header 指向链表头结点
Link<E>* tail; // Pointer to last element 指向链表最后一个结点
Link<E>* curr; // Access to current element 指向当前元素
int cnt; // Size of list 当前列表大小
void init() { // Intialization helper method 初始化
curr = tail = head = new Link<E>;
cnt = 0;
}
void removeall(){
while(head != NULL){
curr = head;
head = head->next;
delete curr;
}
}
public:
Mylist(int size=100) { init(); } // Constructor 构造函数
~Mylist() { removeall(); } // Destructor 析构函数
void print() const; // Print list contents 打印列表内容
void clear() { removeall(); init(); } // Clear list清空列表
// Insert "it" atcurrent position 在当前位置插入“it”
void insert(const E& it) {
curr->next = new Link<E>(it, curr->next);
if (tail == curr) tail = curr->next; // New tail 新的尾指针
cnt++;
}
void append(const E& it) { // Append "it" to list 在列表的尾部追加“it”
tail = tail->next = new Link<E>(it, NULL);
cnt++;
}
// Remove and return current element 删除并返回当前元素
E remove() {
assert(curr->next != NULL); //"Noelement" 若当前没有元素则中断程序
E it = curr->next->element; // Remember value 保存元素值
Link<E>*ltemp = curr->next; // Remember link node保存指针域信息
if (tail == curr->next) tail = curr; // Reset tail 重置尾指针
curr->next = curr->next->next; // Remove from list从列表中删除
delete ltemp; // Reclaim space 回收空间
cnt--; // Decrement the count 当前链表长度减一
return it;
}
void moveToStart() // Place curr at list start将curr设置在链表头部
{ curr = head; }
void moveToEnd() // Place curr at list end 将curr设置在链表尾部
{curr = tail; }
// Move curr one step left; no change ifalready at front
// 将curr指针往前移一步;如果已经指向头部了就不需要改变
void prev() {
if (curr == head) return; // No previous element 若当前指针是头指针直接返回
Link<E>* temp = head;
// March down list until we findthe previous element 循环链表直到找到前一个元素
while (temp->next!=curr) temp=temp->next;
curr = temp;
}
// Move curr one step right; no changeif already at end
//将curr指针往后移一步;如果已经指向尾部了就不需要改变
void next()
{if (curr != tail) curr = curr->next; }
int length() const { return cnt; } // Return length 返回当前列表大小
// Return the position of the current element 返回当前元素的位置
int currPos() const {
Link<E>* temp = head;
int i;
for (i=0; curr != temp; i++)
temp = temp->next;
return i;
}
// Move down list to "pos" position 向下移动到列表“pos”位置
void moveToPos(int pos) {
assert ((pos>=0)&&(pos<=cnt));//"Position out of range" 不在范围内
curr = head;
for(int i=0; i<pos; i++) curr = curr->next;
}
const E& getValue() const { // Return current element 返回当前元素
assert(curr->next != NULL);//"No value" 内容为空
return curr->next->element;
}
};
demo:
#include <iostream>
#include"List.h"
#include"Link.h"
#include"Mylist.h"
#include<stdlib.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
Mylist<int> array(20);
int n,i;
cout<<"基于顺序表实现线性表的基本操作如下:"<<endl<<endl;
cout<<"1.向顺序表中添加10个100以内的随机数元素"<<endl;
for(i=0;i<10;i++)
array.append(rand()%(100-1+1)+1);
cout<<"顺序表当前所有元素为:";
for(i=0;i<array.length();i++){
array.moveToPos(i);
cout<<array.getValue()<<' ';
}
cout<<endl<<endl;
cout<<"2.将当前位置设置成3"<<endl;
array.moveToPos(3);
cout<<"当前位置为:"<<array.currPos()<<endl<<endl;
cout<<"3.删除当前位置元素"<<endl;
array.remove();
cout<<"顺序表当前所有元素为:";
for(i=0;i<array.length();i++){
array.moveToPos(i);
cout<<array.getValue()<<' ';
}
cout<<endl<<endl;
cout<<"4.计算当前元素个数:";
cout<<"当前元素个数为:"<<array.length()<<endl<<endl;
cout<<"5.在当前位置插入元素5"<<endl;
array.insert(5);
cout<<"顺序表当前所有元素为:";
for(i=0;i<array.length();i++){
array.moveToPos(i);
cout<<array.getValue()<<' ';
}
return 0;
}