顺序表的实现
顺序表是在计算机内存中以数组形式保存的线性表,是指用一组地址连续的储存单元依次存储数据元素的线性结构。线性表采用顺序储存的储存方式就称之为顺序表。
今天,我们用C++来实现一种简单的顺序表
首先,建立顺序表的结构模型:
给出 Seqlist.h 文件来构造顺序表的框架和一些函数功能的实现
#ifndef _SEQLIST_H_
#define _SEQLIST_H_ 这是C和C++定义头文件的一个技巧,作用是: 如果程序没有定义Seqlist.h文件,则定义 文件, 这样做的好处是,有效的防止了同一个头文件重复定义。当然 别忘了最 后#endif
#include<iostream>
#include<malloc.h>
using namespace std;
template<typename Type> //我们用模板来定义类型,使得各个数据类型都可以实现
class SeqList class 定义出 SeqList 这个类
{
public:
SeqList(int sz = DEFAULT_SIZE); //构造的函数,其中sz 是顺序表的 容量
~SeqList(); //析构函数 ,其实不用声明也默认存在
public:
bool IsFull()const // 顺序表的判空 判满,这些 都是我们构造顺序表所必须的
{return size>=capacity;}
bool IsEmpty()const
{return size == 0;}
private: //然后我们在私有成员里定义出顺序表的数据。
enum{DEFAULT_SIZE=8}; // 使用枚举类型全局有效
Type *base; 这是我们定义的 Type 类型的指针
int capacity;
int size; 以及顺序表所实现的数组元素数量标记,这方便对数组进行操作
};
我们在定义一些函数操作
public:
void push_back(const Type &x); 尾插
void push_fornt(const Type &x); 头插
void show_seqlist()const; 顺序表的显示
void sort_seqlist(); 顺序表的排序
void pop_back(); 头删
void pop_fornt(); 尾 删
void insert_pos(const Type &x, const int &pos); 按 位置插入
void insert_value(const Type &x); 按数据插入
void delete_pos(int &pos); 按位置删除
void delete_value(const Type &x); 按数值删除
Type find_pos(const int &pos); 按位置查值
int *find_value(const Type &x, int &num); 按数据查值
int length_seqlist(); 长度
void clear();
void resver(); 逆序
void remove_all(const Type &x); 删除所有相同的要求数
};
下面给出我所写的这些函数的实现方法。
首先在实现函数时,别忘了我们模板的定义, template 是模板的关键字 调用时可以使用任意类型的 Type.
template<typename Type>
SeqList<Type>::SeqList(int sz) 在public 外实现函数,我们要加上函数 :: 所在域。
{
capacity = sz > DEFAULT_SIZE ? sz : DEFAULT_SIZE;
base = new Type[capacity];
size = 0;
}
template<typename Type>
SeqList<Type>::~SeqList()
{
delete []base;
base = NULL;
capacity = size = 0;
}
template<typename Type>
void SeqList<Type>::push_back(const Type &x) 尾插法很简单,将数据写入base 再将size++ 就可以啦
{
if(!IsFull())
{
base[size++] = x;
}else{
cout<<"sorry,is full!"<<endl<<"the biggest size: "<< size <<endl;
}
}
template<typename Type>
void SeqList<Type>::push_fornt(const Type &x) 头插法比尾插法复杂一点,关键在于将数据插入头部时不能覆
{ 盖原始数据,否则会使原始数据丢失,所以要将数据往后移
if(!IsFull()) 从最后一个数据开始移动,直到 base[0]。 在将base[0]=x,写入
{
for(int i = size; i >= 0; --i){
base[i] = base[i-1];
}
base[0] = x;
++size;
}else{
cout<<"sorry,is full!"<<endl<<"the biggest size: "<< size <<endl;
}
}
template<typename Type>
void SeqList<Type>::insert_pos(const Type &x,const int &pos)
{
if(!IsFull())
{
if(pos > 0 && pos <= size+1){ 先找出位置,在相当于头插法插入
if(pos == size+1){
++size;
base[size-1] = x;
}else{
for(int i = size; i >= pos; --i){
base[i] = base[i-1];
}
base[pos-1] = x;
++size;
}
}else
cout<<"wrong pos!"<<endl<<"Please insert 1 ~"<< size+1 <<endl;
}else{
cout<<"sorry,is full!"<<endl<<"the biggest size: "<< size <<endl;
}
}
template<typename Type>
void SeqList<Type>::insert_value(const Type &x) 按值插入,我们就不得不先进行排序,调用后面的排序 函数。
{
if(!IsFull()){
sort_seqlist();
int i;
int temp = 0;
base[size] = x;
for(i = size-1; i >= 0 && base[i] > base[i+1]; --i){
temp = base[i+1];
base[i+1] = base[i];
base[i] = temp;
}
++size;
}else{
cout<<"sorry,is full!"<<endl<<"the biggest size: "<< size <<endl;
}
}
template<typename Type>
void SeqList<Type>::pop_back()
{
if(size != 0){
cout<<base[size-1]<<"已删除!"<<endl;
--size;
}else
cout<<"sorry,no num!"<<endl;
}
template<typename Type> 这些简单的就不用多讲了
void SeqList<Type>::pop_fornt()
{
if(size != 0){
cout<<base[0]<<"已删除!"<<endl;
for(int i = 0; i < size; ++i){
base[i] = base[i+1];
}
--size;
}else
cout<<"sorry,no num!"<<endl;
}
template<typename Type>
void SeqList<Type>::delete_pos(int &pos)
{
if(size != 0){
if(pos > 0 && pos <= size){
cout<<base[pos-1]<<"已删除!"<<endl;
for(int i = pos-1; i < size; ++i){ 编写函数时一定要注意程序的鲁棒性,及程序调用的各种情况都要
base[i] = base[i+1]; 考虑,不能让程序 “无方法可选" ,比如按位置删除的函数,我们必
} 需对位置的范围进行限制。
--size;
}else{
cout << "please inseart " <<" 1 ~ "<< size << endl;
}
}else
cout<<"sorry,no num!"<<endl;
}
template<typename Type>
void SeqList<Type>::delete_value(const Type &x)
{
sort_seqlist();
int i;
for(i = 0; i < size; ++i){
if(base[i] == x)
break;
}
if(i != size){
for(int j = i+1; j < size; ++j){
base[j-1] = base[j];
}
--size;
}else
cout<<"sorry,no this num!"<<endl;
}
template<typename Type>
void SeqList<Type>::remove_all(const Type &x) 在编写程序时另一点要注意的就是尽量“偷懒“,即就是函数的重用
{ 行,在这个函数中,我们要删除所有相同的数
if(size != 0){ 比如 1 3 2 4 2 3 8 14 如果要删除2 就要把所有2都删除。
int num = 0; 首先 要先找出2的位置, 很巧我们在上面实现的这个功能
int pos = -1; find_pos 函数,所以调用,找出2的所有位置。
int *p = find_value(x, num); 然后按位置删除,很巧 ,我们在上面同样实现了这个函数
if(p != NULL){ delete_pos, 我们在进行调用。
for(int i = 0; i < num; i++){ 如果直接调用,程序结果是错误的,为什么呢?
pos = p[i] - i; —————————————————— 注意关键 在这里,当我们删掉第一个位置的2后,其他的位
delete_pos(pos); 置其实都向前移动了一个位置,删除依次,向前移动依次,所以原
} 本的位置不可用,我们要进行调整。即就是p[i] - i;
}else{
cout << "sorry, wrong num!"<<endl;
}
}else{
cout << "sorry, no num!" << endl;
}
}
template<typename Type>
void SeqList<Type>::show_seqlist()const
{
for(int i=0; i<size; ++i)
{
cout<<base[i]<<" ";
}
cout<<endl;
}
template<typename Type>
Type SeqList<Type>::find_pos(const int &pos)
{
if(size != 0){
if(pos > 0 && pos <= size){
cout << "第" << pos << "个数是: " << base[pos-1] << endl;
return base[pos-1];
}else{
cout << "please inseart " <<" 1 ~ "<< size << endl;
}
}else
cout<<"sorry,no num!"<<endl;
}
template<typename Type>
int *SeqList<Type>::find_value(const Type &x, int &num)
{
bool j = false;
int *pos_array = (int *)malloc(sizeof(int) * size);
if(size != 0){
for(int i = 0; i < size; ++i){
if(base[i] == x){
cout << i+1 << ",";
j = true;
pos_array[num] = i + 1; //将所有查找到的位置记录于数组并返回
++num;
}
}
if(j == true){
cout << "是" << x << "所在的位置" << endl;
return pos_array;
}else
cout << "没有找到" << x <<endl;
}else
cout << "sorry, no num!" << endl;
return NULL;
}
template<typename Type> 在这里排序我们用了选择排序法,关于排序的详细解释,
void SeqList<Type>::sort_seqlist() 会在以后给出。
{
if(size != 0){
for(int i = 1; i < size; ++i){
for(int j = i-1; j >= 0 && base[j] > base[j+1]; --j){
int temp = base[j+1];
base[j+1] = base[j];
base[j] = temp;
}
}
}else{
cout << "sorry, no num!";
}
}
template<typename Type>
void SeqList<Type>::resver() 逆序时,用两个指针是个很棒的想法,无疑简化了程序
{
int i = 0;
int j = size-1;
int temp = 0;
if(size != 0){
while(i < j){
temp = base[i];
base[i] = base[j];
base[j] = temp;
i++;
j--;
}
}else{
cout << "no num!" << endl;
}
}
template<typename Type>
void SeqList<Type>::clear()
{
size = 0;
cout << "done!"<<endl;
}
template<typename Type>
int SeqList<Type>::length_seqlist()
{
cout << "长度为: " << size << endl;
return size;
}
#endif
这样我们就完成了Seqlist.h 的代码部分,就下来就是main()函数的实现了
上代码
#include<iostream>
#include"test.h"
using namespace std;
int main()
{
SeqList<int> mylist; 在这里就是模板的类型选择了,我们用int 做个示范
int select = 1;
int pos = -1;
int Item = -1;
int num = 0;
while(select)
{
cout<<"*****************************************************"<<endl;
cout<<"* [1] push_back(-1结束) [2] push_fornt(-1结束) *"<<endl;
cout<<"* [3] show_seqlist [0] quit system *"<<endl;
cout<<"* [4] pop_back [5] pop_fornt *"<<endl;
cout<<"* [6] insert_pos [7] insert_value *"<<endl;
cout<<"* [8] delete_pos [9] delete_value *"<<endl;
cout<<"* [10] find_pos [11] find_value *"<<endl;
cout<<"* [12] sort [13] resver *"<<endl;
cout<<"* [14] clear [15] length *"<<endl;
cout<<"* [16] remove_all &[17] destroy *"<<endl;
cout<<"*****************************************************"<<endl;
cout<<"请选择:>";
cin>>select;
switch(select)
{
case 0:
return 0; 主函数这块没什么用讲的, 注意一点 是mylist类下的函
case 1: 数,所以用mylist.的方式调用。
cout<<"请输入要插入的数据(以-1结束)//尾插:";
while(cin>>Item, Item != -1)
{
mylist.push_back(Item);
}
break;
case 2:
cout<<"请输入要插入的数据(以-1结束)//头插:";
while(cin>>Item, Item != -1)
{
mylist.push_fornt(Item);
}
break;
case 3:
mylist.show_seqlist();
break;
case 4:
mylist.pop_back();
mylist.show_seqlist();
break;
case 5:
mylist.pop_fornt();
mylist.show_seqlist();
break;
case 6:
cout<<"请输入要插入的数据,和位置(-1 0结束):"<<endl;
while(cin>>Item, Item != -1)
{
cin>>pos;
mylist.insert_pos(Item, pos);
mylist.show_seqlist();
}
break;
case 7:
cout<<"请输入要插入的数据(-1 结束):"<<endl;
while(cin>>Item, Item != -1)
{
mylist.insert_value(Item);
mylist.show_seqlist();
}
break;
case 8:
cout << "请输入要删除的位置(-1结束)"<< endl;
while(cin >> pos, pos != -1){
mylist.delete_pos(pos);
mylist.show_seqlist();
}
break;
case 9:
cout<<"请输入要删除的数据(-1 结束):"<<endl;
while(cin>>Item, Item != -1)
{
mylist.delete_value(Item);
mylist.show_seqlist();
}
break;
case 10:
cout << "请输入要查找的位置 (-1结束):" << endl;
while(cin >> pos, pos != -1){
mylist.find_pos(pos);
mylist.show_seqlist();
}
break;
case 11:
cout << "请输入要查找的数据 (-1结束)" << endl;
while(cin >> Item, Item != -1){
mylist.find_value(Item, num);
mylist.show_seqlist();
}
break;
case 12:
mylist.sort_seqlist();
mylist.show_seqlist();
break;
case 13:
mylist.resver();
mylist.show_seqlist();
break;
case 14:
mylist.clear();
break;
case 15:
mylist.length_seqlist();
break;
case 16:
cout << "请输入要删除的数据 (-1结束)" << endl;
while(cin >> Item, Item != -1){
mylist.remove_all(Item);
mylist.show_seqlist();
}
break;
}
}
return 0;
}
这样我们就完成了整个顺序表代码的实现,看看运行结果吧!
我们顺序表的实现的成功的。
第一次写博客,水平有限,但只要写博客能持之以恒,能力一定能够提高。加油!
染尘 4.9