顺序表及其基本方法的实现
定义:顺序表使用一组地址连续的存储单元依次存储线性表中的数据元素。
特点:线性表的顺序存储结构是一种随机存取的存储结构,支持通过下标快速访问元素;但在元素插入和删除时效率比较低,需要移动插入(或删除)位置后面的所有元素。
在顺序表中某个位置上插入或删除一个元素,其时间主要消耗在移动元素上,而移动元素的个数取决于插入或删除元素的位置。
假设顺序表中有n个元素,在每个位置上插入或删除的概率相等,则插入操作平均需要移动的元素个数为n/2,删除操作平均需要移动的元素个数为(n-1)/2。
//顺序表的实现和基本方法
#include<iostream>
#include<iomanip>
#include<stdlib.h>
#include<string.h>
using namespace std;
const int LIST_INIT_SIZE = 20; //顺序表的初始化容量
const int LISTINCREMENT = 10; //顺序表的步长
typedef int ElemType; //元素类型
//顺序表的结构
struct SqList{
ElemType *elem; //基址
int length; //当前元素个数
int listsize; //当前容量
};
//初始化一个顺序表
bool InitList_Sq(SqList &L){
L.elem = (ElemType*) malloc(sizeof(ElemType)*LIST_INIT_SIZE);
if(!L.elem)return false; //初始化失败
L.length = 0;
L.listsize = LIST_INIT_SIZE;
return true;
}
//销毁顺序表
void Destroy_Sq(SqList &L){
free(L.elem);
L.elem = NULL;
}
//遍历顺序表
void Traverse_Sq(SqList &L){
for(int i=0; i<L.length; ++i){
cout<<setw(5)<<*(L.elem+i);
}
cout<<endl;
}
//在第i个位置前插入一个元素
bool ListInsert_Sq(SqList &L, int i, ElemType e){
if(i<1 || i>L.length+1)return false; //检查插入位置
if(L.length >= L.listsize){ //动态自增长
ElemType *newbase = (ElemType*) realloc(L.elem,
sizeof(ElemType)*(LISTINCREMENT+L.listsize));
if(!newbase)return false;
L.elem = newbase;
L.listsize += LISTINCREMENT;
}
ElemType *q = &(L.elem[i-1]); //指向插入位置
ElemType *p = &(L.elem[L.length-1]); //指向最后一个元素
for(; p>=q; --p) //i之后的元素往后移动一个位置
*(p+1) = *p;
*q = e;
++L.length;
return true;
}
//删除第i个元素,并将其拷贝到e中
bool ListDelete_Sq(SqList &L, int i, ElemType &e){
if(i<1 || i>L.length)return false;
ElemType *q = &(L.elem[i-1]); //删除位置
e = *q;
for(++q; q<(L.elem+L.length); ++q)//往前移动元素
*(q-1) = *q;
--L.length;
return true;
}
//查找,返回第一个符合条件(由compare确定)的元素的索引值
int LocateElem_Sq(SqList &L, ElemType e, bool (*cmp)(ElemType, ElemType)){
ElemType *p = L.elem;
int i = 1;
while(i<=L.length && !(*cmp)(*p++,e))++i;
if(i<=L.length)return i;
else return 0;
}
//这个比较函数用来寻找与指定值相等的元素
bool compare(ElemType a, ElemType b){
return a == b;
}
//归并排序
void MergeList_Sq(SqList La, SqList Lb, SqList &Lc){
ElemType *pa = La.elem;
ElemType *pa_last = La.elem + La.length - 1;
ElemType *pb = Lb.elem;
ElemType *pb_last = Lb.elem + Lb.length -1;
Lc.listsize = Lc.length = La.length + Lb.length;
ElemType *pc = Lc.elem = (ElemType*) malloc(sizeof(ElemType)*Lc.listsize);
if(!Lc.elem)return; //存储分配失败
while(pa<=pa_last && pb<=pb_last){
if(*pa<=*pb)*pc++=*pa++;
else *pc++=*pb++;
}
while(pa<=pa_last)*pc++=*pa++;
while(pb<=pb_last)*pc++=*pb++;
}
int main(){
SqList L;
InitList_Sq(L);
//插入和删除操作
cout<<"插入操作"<<endl;
for(int n=1; n<=10; ++n)ListInsert_Sq(L,1,n);
Traverse_Sq(L);
cout<<"删除操作"<<endl;
ElemType e;
ListDelete_Sq(L,3,e);
Traverse_Sq(L);
//查找
cout<<"查找操作"<<endl;
bool (*pcmp)(ElemType, ElemType) = compare;
cout<<LocateElem_Sq(L,4,pcmp)<<endl;
//合并排序
cout<<"归并排序"<<endl;
SqList L1,L2,L3;
InitList_Sq(L1);
L1.length = 5;
int n = 1;
for(ElemType *p=L1.elem;p<L1.elem+L1.length;++p){*p=2*n+1;++n;}
InitList_Sq(L2);
L2.length = 8;
n = 1;
for(ElemType *p=L2.elem;p<L2.elem+L2.length;++p){*p=2*n-1;++n;}
MergeList_Sq(L1,L2,L3);
Traverse_Sq(L1);
Traverse_Sq(L2);
Traverse_Sq(L3);
Destroy_Sq(L);
Destroy_Sq(L1);
Destroy_Sq(L2);
Destroy_Sq(L3);
return 0;
}
结果:
插入操作
10 9 8 7 6 5 4 3 2 1
删除操作
10 9 7 6 5 4 3 2 1
查找
6
归并排序
3 5 7 9 11
1 3 5 7 9 11 13 15
1 3 3 5 5 7 7 9 9 11 11 13 15
注意:归并排序要求待合并的两个序列为有序序列!
by chenqi/20110913