您的位置:首页 > 其它

顺序表的基本操作

2015-04-22 11:14 411 查看
进入数据结构首先接触到的就是线性结构,而顺序表是典型的线性结构。在此我们一起来实现关于顺序表的一些基本操作。

int begin(); //开始位置

int end(SeqList *list); //结束位置

void InitSeqList(SeqList *list);//初始化

bool isempty(SeqList *list);//判断是否为空

bool isfull(SeqList *list);//判断是否为满

bool push_back(SeqList *list,ElemType x);//尾插法

bool push_front(SeqList *list,ElemType x);//头插法

bool pop_back(SeqList *list);//尾删法

bool pop_front(SeqList *list);//头删法

bool insert_pos(SeqList *list, int p, ElemType x);//按下标插入数据

bool insert_val(SeqList *list, ElemType key,ElemType x);//按数值插入数据

bool delete_pos(SeqList *list, int p);//按下标删除数据

bool delete_val(SeqList *list, ElemType key);//按数据删除数据

int find(SeqList *list,ElemType x);//查找数值的下标

ElemType getvalue(SeqList *list,int p);//查找下标的数值

bool modify_pos(SeqList *list,int p,ElemType x);//通过下标修改数值

bool mosify_val(SeqList *list, ElemType key,ElemType x);//直接修改数值

void clear(SeqList *list);//清除操作

void destroy(SeqList *list);//摧毁操作

void sort(SeqList *list);//排序操作

void resver(SeqList *list);//转置操作

int length(SeqList *list);//求顺序表真实长度

ElemType next(SeqList *list,ElemType key);//求后继

ElemType prio(SeqList *List,ElemType key);//求前驱

void show(SeqList *list);//显示顺序表

以上为需要实现的函数功能

具体的代码如下:

首先是头文件

#ifndef _SEQLIST_H       //防止头文件重复引用
#define _SEQLIST_H

#include <iostream>
#include <assert.h>      //断言
#include <malloc.h>
using namespace std;

typedef  int ElemType;   //类型重命名
#define SEQLIST_SIZE 20  //此空间的最大值
#define MIN -1000

typedef struct SeqList   //顺序表的数据结构构造
{
ElemType *base;      //存放数据
size_t size;         //真实长度
size_t length;       //可存储长度
}SeqList;

int begin();             //开始位置
int end(SeqList *list);  //结束位置
void InitSeqList(SeqList *list);//初始化
bool isempty(SeqList *list);//判断是否为空
bool isfull(SeqList *list);//判断是否为满
bool push_back(SeqList *list,ElemType x);//尾插法
bool push_front(SeqList *list,ElemType x);//头插法
bool pop_back(SeqList *list);//尾删法
bool pop_front(SeqList *list);//头删法
bool insert_pos(SeqList *list, int p, ElemType x);//按下标插入数据
bool insert_val(SeqList *list, ElemType key,ElemType x);//按数值插入数据
bool delete_pos(SeqList *list, int p);//按下标删除数据
bool delete_val(SeqList *list, ElemType key);//按数据删除数据
int find(SeqList *list,ElemType x);//查找数值的下标
ElemType getvalue(SeqList *list,int p);//查找下标的数值
bool modify_pos(SeqList *list,int p,ElemType x);//通过下标修改数值
bool mosify_val(SeqList *list, ElemType key,ElemType x);//直接修改数值
void clear(SeqList *list);//清除操作
void destroy(SeqList *list);//摧毁操作
void sort(SeqList *list);//排序操作
void resver(SeqList *list);//转置操作
int length(SeqList *list);//求顺序表真实长度
ElemType next(SeqList *list,ElemType key);//求后继
ElemType prio(SeqList *List,ElemType key);//求前驱
void show(SeqList *list);//显示顺序表

#endif


其次是各个函数的实现代码

#include "SeqList.h"

int begin()//开始即为0
{
return 0;
}

int end(SeqList *list)//末尾即为顺序表长度
{
return list->size ;
}

void InitSeqList(SeqList *list)
{
list->length = SEQLIST_SIZE;
list->base = (ElemType*)malloc(sizeof(ElemType)*list->length);//开辟空间
assert(list->base != NULL);//采用断言查看是否开辟成功
list->size = 0;
}

bool isempty(SeqList *list)
{
return list->size == 0;//为0返回真
}

bool isfull(SeqList *list)
{
return list->size >= list->length ;//满足返回真
}
/*此处是一般方法来实现头插尾插*/
bool push_back(SeqList *list,ElemType x)
{
if(isfull(list))
{
return false;
}
list->base[list->size++] = x;//尾插
return true;
}

bool push_front(SeqList *list,ElemType x)
{
if(isfull(list))
{
return false;
}
for(int i = list->size ;i > 0;--i)//头插需要将之前插入的从后面向前依次移位
{
list->base[i] = list->base[i-1];
}
list->base[0] = x;//插入
list->size++;//长度加一
return true;
}
/*调用后续函数实现功能
bool push_back(SeqList *list,ElemType x)
{
return insert_pos(list,end(list),x);
}
bool push_front(SeqList *list,ElemType x)
{
return insert_pos(list,begin(),x);
}*/

bool pop_back(SeqList *list)
{
if(isempty(list))
{
return false;
}
list->size--;//尾删
return true;
}

bool pop_front(SeqList *list)
{
if(isempty(list))
{
return false;
}
for(int i = 0;i < list->size-1;++i)//头删即从下标为1的数值开始向前移位,但是需要考虑list->size的情况
{
list->base[i] = list->base[i+1];
}
list->size--;//长度减一
return true;
}

bool insert_pos(SeqList *list, int p, ElemType x)
{//根据下标来插入数据
if(isfull(list))
{
return false;
}
if(p<0 || p > list->size)
{
return false;
}
for(int i = list->size;i>p;--i)
{
list->base[i] = list->base[i-1];
}
list->base[p] = x;
list->size++;
return true;
}

bool insert_val(SeqList *list, ElemType key,ElemType x)
{//根据数值来插入数据
for(int i = 0;i<list->size ;++i)
{
if(list->base[i] == key)
{
break;
}
}//此时i的值即为此数下标
if(i>=list->size )
{
return false;
}
for(int k = list->size;k>i ;--k)
{
list->base[k] = list->base[k-1];
}
list->base[i] = x;
list->size++;
return true;
}
/*调用函数实现
bool insert_val(SeqList *list, ElemType key,ElemType x)
{
int pos = find(list,key);
if(pos == -1)
{
return false;
}
for(int k = list->size;k>pos ;--k)
{
list->base[k] = list->base[k-1];
}
list->base[pos] = x;
list->size++;
return true;
}*/

bool delete_pos(SeqList *list, int p)
{//根据下标删除数值
if(isfull(list))
{
return false;
}
if(p<0 || p > list->size)
{
return false;
}
for(int i = p;i<list->size-1;++i)
{
list->base[i] = list->base[i+1];
}
list->size--;
return true;
}

bool delete_val(SeqList *list, ElemType key)
{//根据数值删除数值
for(int i=0; i<list->size; ++i)
{
if(list->base[i] == key)
{
break;
}
}
if(i >= list->size)
return false;
for(int k=i; k<list->size-1; ++k)
{
list->base[k] = list->base[k+1];
}
list->size--;
return true;
}

/*调用函数实现
bool delete_val(SeqList *list, ElemType key)
{
int pos = find(list,key);
if(pos == -1)
return false;
delete_pos(list,pos);
return true;
}*/

int find(SeqList *list,ElemType x)//通过数值找其下标
{
if(isempty(list))
{
return false;
}
for(int i = 0;i < list->size ;++i)
{
if(x == list->base[i])
{
return i;
}
}
return -1;
}

ElemType getvalue(SeqList *list,int p)//通过下标找其值
{
if(isfull(list))
{
return false;
}
if(p<0 || p > list->size)
{
return false;
}
return list->base[p];
}

bool modify_pos(SeqList *list,int p,ElemType x)//通过下标找到数值并修改
{
if(isempty(list))
{
return false;
}
for(int i = 0;i < list->size;++i)
{
if(p == i)
{
break;
}
}
list->base[i] = x;
return true;
}

bool mosify_val(SeqList *list, ElemType key,ElemType x)//直接修改所需要修改的数值
{
int pos = find(list,key);
if(pos == -1)
{
return false;
}
modify_pos(list,pos,x);
return true;
}

void clear(SeqList *list)//清除顺序表
{
list->size = 0;
}

void destroy(SeqList *list)//摧毁顺序表
{
free(list->base);
list->base = NULL;
list->size = 0;
list->length = 0;
}
void sort(SeqList *list)//顺序表排序
{
if(isempty(list))
{
return;
}
int i,j;
bool ischanged;
for(j = list->size-1 ;j > 0;--j)
{
ischanged = false;
for(i = 0;i < j;++i)
{
if(list->base[i]>list->base [i+1])
{
int temp = list->base[i];
list->base[i] = list->base[i+1];
list->base[i+1] = temp;
ischanged = true;
}
}
if(!ischanged)
{
break;
}
}
}
void resver(SeqList *list)//顺序表转置
{
int temp = 0;
if(isempty(list))
{
return;
}
for(int i = 0,j = list->size-1;i < j; ++i,--j)
{
temp = list->base[i];
list->base[i] = list->base[j];
list->base[j] = temp;
}
}
int length(SeqList *list)//顺序表长度
{
return list->size;
}
ElemType next(SeqList *list,ElemType key)//顺序表数值后继
{
int pos = find(list,key);
if(pos == -1 || pos == list->size-1)
{
return false;
}
return list->base[pos+1];
}
ElemType prio(SeqList *list,ElemType key)//顺序表数值前驱
{
int pos = find(list,key);
if(pos == -1 || pos == 0)
{
return false;
}
return list->base[pos-1];
}
void show(SeqList *list)//显示顺序表
{
for(int i=0; i<list->size; ++i)
{
cout<<list->base[i]<<" ";
}
cout<<endl;
}


可以看出对于一个函数可以有多种方法解决,但是函数调用函数是比较简便的,可以减少代码的重复。

最后就是测试

#include"SeqList.h"
/*测试程序*/
int main()
{
SeqList mylist;
InitSeqList(&mylist);

int select = 1;
ElemType item;
ElemType date;
int pos;
while(select)
{
cout<<"*************************************"<<endl;
cout<<"* [0]  quit_system [1]  push_back   *"<<endl;
cout<<"* [2]  push_front  [3]  show_seqlist*"<<endl;
cout<<"* [4]  pop_back    [5]  pop_front   *"<<endl;
cout<<"* [6]  insert_pos  [7]  insert_val  *"<<endl;
cout<<"* [8]  delete_pos  [9]  delete_val  *"<<endl;
cout<<"* [10] find        [11] getvalue    *"<<endl;
cout<<"* [12] modify_pos  [13] modify_val  *"<<endl;
cout<<"* [14] clear       [15] destroy     *"<<endl;
cout<<"* [16] sort        [17] resver      *"<<endl;
cout<<"* [18] length      [19] next        *"<<endl;
cout<<"* [20] prio                         *"<<endl;
cout<<"*************************************"<<endl;
cout<<"请选择:>";
cin>>select;
switch(select)
{
case 1:
cout<<"请输入要插入的数据(-1结束):>";
while(cin>>item,item!=-1)
{
push_back(&mylist,item);
}
break;
case 2:
cout<<"请输入要插入的数据(-1结束):>";
while(cin>>item,item!=-1)
{
push_front(&mylist,item);
}
break;
case 3:
show(&mylist);
break;
case 4:
pop_back(&mylist);
break;
case 5:
pop_front(&mylist);
break;
case 6:
cout<<"请输入要插入的位置:>";
cin>>pos;
cout<<"请输入要插入的值:>";
cin>>item;
insert_pos(&mylist,pos,item);
break;
case 7:
cout<<"请输入要插入位置所在的值:>";
cin>>pos;
cout<<"请输入要插入的值:>";
cin>>item;
insert_val(&mylist,pos,item);
break;
case 8:
cout<<"请输入要删除值的位置:>";
cin>>pos;
delete_pos(&mylist,pos);
break;
case 9:
cout<<"请输入要删除的值:>";
cin>>item;
delete_val(&mylist,item);
break;
case 10:
cout<<"请输入想要查询的值:>";
cin>>item;
cout<<"该值的下标为:>"<<find(&mylist,item)<<endl;
break;
case 11:
cout<<"请输入想要查询值的下标:>";
cin>>pos;
cout<<"该值是:>"<<getvalue(&mylist,pos)<<endl;
break;
case 12:
cout<<"请输入想要修改数值的下标:>";
cin>>pos;
cout<<"请输入修改的值:>";
cin>>item;
modify_pos(&mylist,pos,item);
break;
case 13:
cout<<"请输入想要修改的数值:>";
cin>>item;
cout<<"请输入修改的值:>";
cin>>date;
mosify_val(&mylist,item,date);
break;
case 14:
clear(&mylist);
break;
case 15:
destroy(&mylist);
break;
case 16:
sort(&mylist);
break;
case 17:
resver(&mylist);
break;
case 18:
cout<<length(&mylist)<<endl;
break;
case 19:
cout<<"请输入想要查询的数值:>";
cin>>item;
cout<<"该数值的后继是:>"<<next(&mylist,item)<<endl;
break;
case 20:
cout<<"请输入想要查询的数值:>";
cin>>item;
cout<<"该数值的前驱是:>"<<prio(&mylist,item)<<endl;
break;
default:
break;
}
}
return 0;
}


运行的截图如下:
首先是主界面



然后开始功能的测试

1.尾插法



按3输出结果为



2.头插法



按3结果表示



3.尾删法



按3输出结果为



4.头删法



按3输出结果为



5.根据下标插入数值



按3输出结果



6.根据数值位置插入数值



按3输出结果



7.根据下标删除数值



按3输出结果为



8.根据数值直接删除



按3输出结果



9.根据数值找到其下标



10.根据其下标找到该值



11.根据下标查找到所修改的值并修改



按3输出结果是



12.直接找到所需要修改的值进行修改



按3输出结果是



13.排序



按3输出结果



14.倒置



按3输出结果



15.顺序表的长度



16.求后继



17.求前驱



18.清除顺序表



按18输出结果可知此时顺序表长度



程序中还有一些考虑不全面的地方希望大家可以指出。

此算法还有许多可以改进的地方:

对于排序有很多种方法,可以自己尝试。而当我们的顺序表有序后,find()函数即可用二分查找实现,代码如下:

int find(SeqList *list,ElemType x)//通过数值找其下标
{
sort(list);
int left = 0;
int right = list->size-1;
int mid;
while(left <= right)
{
mid = (left+right)/2;
if(x > list->base[mid])
{
left = mid+1;
}
else if(x < list->base[mid])
{
right = mid-1;
}
else
{
return mid;
}
}
return -1;
}
还有一种改进方式,即顺序表可以自动增加长度~代码如下:

#define INC_SIZE 3
bool Inc(SeqList *list)
{
list->length += INC_SIZE;
list->base = realloc(list->base ,sizeof(ElemType)*list->length);
if(list->base == NULL)
{
return false;
}
return true;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: