///顺序表:::
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define ERROR -1
#define bool char
#define ture 1
#define false 0
#define OVERFLOW -2
#define OK 1
#define LIST_INIT_SIZE 100 ///线性表存储空间的初始分配量
#define LISTINCREMENT 10 ///线性表存储空间分配增量
///说明开始向全用c写,太鸡巴麻烦了,还是换c++吧
typedef struct
{
int *elem; /// 存储空间基址
int length; /// 当前长度
int listsize; /// 当前分配的存储容量(以sizeof(int)为单位)
}SqList;
bool InitList_Sq(SqList* L) /// 构造一个空的线性表L
{
(*L).elem = (int *)malloc(LIST_INIT_SIZE * sizeof(int));
if(!(*L).elem) exit(OVERFLOW); /// 存储分配失败
(*L).length = 0; /// 当前长度,当前为空表,0
(*L).listsize = LIST_INIT_SIZE; /// 初始化存储容量
return OK;
}//InitList_Sq
void Scanf_Sq(SqList &L,int n)
{
/// 输入n个值放入顺序表
printf("请输入顺序表:");
for(int i=0;i<n;i++)
scanf("%d",&L.elem[i]);
L.length = n;
return ;
}
void Printf_Sq(SqList &L)
{
/// 输出整个顺序表,用2个空格隔开
printf("顺序表为:");
for(int i=0;i<L.length;i++)
printf("%d ", L.elem[i]);
printf("\n");
}
void DestroyList(SqList &L)
{
/// 销毁线性表
if(L.elem) /// 如果L.elem里分配了值的话
free(L.elem);
L.elem = NULL;
return;
}
void ClearList(SqList &L)
{
/// 将L置为空表
if(L.length)
L.length = 0;
return ;
}
bool ListEmpty(SqList L)
{
/// 判空
/// 若L为空表,返回true,否则返回false
return !L.length;
}
int ListLength(SqList L)
{
/// 返回L中数据元素的个数
return L.length;
}
bool GetElem(SqList L,int i,int &e)
{
/// 1<=i<=ListLength(L)
/// 用e返回L中的第i个数据元素
if( 1 <= i || i <= L.length){
e = L.elem[i-1];
return OK;
}
else return false;
}
bool ListInsert_Sq(SqList &L, int i, int e)
{
///在顺序线性表L中第i个位置之前插入新的元素e
///i的合法值为1<=i<=ListLength_Sq(L)+1
if(i < 1 || i > L.length + 1) return ERROR; ///i值不合法
if(L.length >= L.listsize){ /// 当前存储空间已满增加分配
int *newbase = (int *)realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(int) );
if(!newbase) exit(OVERFLOW); ///存储分配失败
L.elem = newbase; ///新基址
L.listsize += LISTINCREMENT; ///增加存储容量
}
int *q = &(L.elem[i-1]); ///注意,顺序表和数组一样,i个元素是L.elem[i-1]
for(int *p = &(L.elem[L.length-1]); p>=q ;p--) *(p+1) = *p;
/// 插入位置级及后的元素右移
*q = e; /// 插入e
L.length += 1; /// 表长增长1
return OK;
}
bool PriorElem(SqList L, int cur_e, int & pre_e)
{
/// 返回cur_e的前趋
/// 若cur_e是L的数据元素,且不是第一个,用pre_e返回它的前驱
for(int i=1;i<L.length;i++)
if(L.elem[i] == cur_e) {
pre_e = L.elem[i-1];
return OK;
}
return false;
}
bool NextElem(SqList L, int cur_e, int & next_e)
{
/// 返回cur_e的前趋
/// 若cur_e是L的数据元素,且不是最后一个,用pre_e返回它的后继
for(int i=0;i<L.length-1;i++)
if(L.elem[i] == cur_e) {
next_e = L.elem[i+1];
return OK;
}
return false;
}
bool ListDelete_Sq(SqList &L, int i, int &e)
{
/// 在顺序线性表L中删除第i个元素,并用e返回其值
/// i的合法范围1<=i<=ListLength_Sq(L)
if(i < 1 || i > L.length) return ERROR; /// i值不合法
int *p = &(L.elem[i-1]); /// p为被删除元素的位置
e = *p; /// 被删除元素的值赋给e
int *q = L.elem + L.length -1; /// 表尾元素的位置
for( p++ ; p<=q ;p++) *(p-1) = *p; /// 被删除之后的元素左移
L.length--; /// 表长减1
return OK;
}
bool compare(int a,int b){ return a>b; }
int LocateElem_Sq(SqList &L, int e, bool (* compare)(int ,int ) )
{
/// 在顺序表L中查找第一个值与e满足compare()的元素的位序
/// 若找到返回位序,否则返回0
int i = 1; ///i的初值,为第一个元素的位序
int * p = L.elem; /// p的初值为第一个元素的存储位置
while (i <= L.length && !(* compare)(*p++,e)) ++i;
if(i <= L.length) return i;
return 0;
}// LocateElem_Sq
void MergeList_Sq(SqList La, SqList Lb, SqList &Lc)
{
/// 已知顺序表La和Lb的元素按值非递减排列
/// 归并La和Lb得到的新的顺序表Lc,Lc的元素也是按非递减排列的
int *pa = La.elem, *pb = Lb.elem;
Lc.listsize = Lc.length = La.length + Lb.length;
int *pc = Lc.elem = (int *)malloc(Lc.listsize*sizeof(int));
if(!Lc.elem) exit(OVERFLOW); /// 存储分配失败
int *pa_last = La.elem + La.length -1;
int *pb_last = Lb.elem + Lb.length -1;
while(pa <= pa_last && pb <= pb_last){ /// 归并
if(*pa <= *pb) *pc++ = *pa++;
else *pc++ = *pb++;
}
while(pa <= pa_last) *pc++ = *pa++; /// 插入La中的剩余元素
while(pb <= pb_last) *pc++ = *pb++; /// 插入Lb中的剩余元素
return ;
}// MergeList_Sq
bool visit(int &x)
{
x+=1;
return OK;
}
bool ListTraverse(SqList L, bool visit(int & x))
{
/// 依次对L的每个数据元素调用visit(),一旦visit()调用失败,操作失败
/// 我写的是对每个元素进行+1操作
for(int i=0;i<L.length;i++)
if( !(* visit )( L.elem[i] ) ) return false;
return OK;
}
bool Equal(int a,int b){ return a== b; }
void union_Sq(SqList &La, SqList Lb)
{
/// 将所有线性表Lb中的但不在La中的数据元素插入到La中
int cur_e=0;
int La_len = ListLength(La), Lb_len = ListLength(Lb); ///求线性表的长度
for(int i=1;i<=Lb_len;i++){
GetElem(Lb,i,cur_e); /// 驱Lb中第i个元素赋给e
if(!LocateElem_Sq(La,cur_e,Equal)) ListInsert_Sq(La, ++La_len,cur_e);
/// La中不存在和e相同的数据元素,则插入
}
}//union
void MergeList(SqList La, SqList Lb, SqList &Lc)
{
/// 已知线性表La和Lb中的元素按非递减排列
/// 归并La和Lb得到新的线性表Lc,Lc的数据元素也按非递减排列
InitList_Sq(&Lc);
int i = 1,j = 1, k = 0;
int ai =0, bj = 0;
int La_len = ListLength(La), Lb_len = ListLength(Lb);
while( (i<=La_len) && (j <= Lb_len) ){ /// La和Lb均为非空
GetElem(La,i,ai); GetElem(Lb,j,bj);
if(ai <= bj) { ListInsert_Sq(Lc, ++k, ai); ++i; }
else { ListInsert_Sq(Lc, ++k, bj); ++j; }
}
while(i <= La_len) {
GetElem(La,i,ai);
ListInsert_Sq(Lc, ++k, ai); ++i;
}
while(j <= Lb_len) {
GetElem(Lb,j,bj);
ListInsert_Sq(Lc, ++k, bj); ++j;
}
}//MergeList
int main()
{
SqList L; /// 定义一个顺序表
InitList_Sq(&L); ///初始化顺序表L
printf("请输入需要输入顺序表的个数n:");
int n;
scanf("%d",&n);///
Scanf_Sq(L,n);/// 从0开始读入n个顺序表
Printf_Sq(L); /// 输出当前的顺序表
printf("\n");
/// 测试插入
ListInsert_Sq(L,6,6);
Printf_Sq(L);
printf("\n");
/// 测试删除
int e;
ListDelete_Sq(L,6,e);
Printf_Sq(L);
printf("被删除的元素是:%d\n",e);
printf("\n");
/// 测试第一个与e大或者小的数,返回其位序
printf("请输入要判断位序的e:");
scanf("%d",&e);
printf("%d\n",LocateElem_Sq(L,e,compare) );
printf("\n");
///测试归并
SqList Lc,Lb;
InitList_Sq(&Lb);
InitList_Sq(&Lc);
printf("请输入需要输入顺序表Lb的个数n:");
scanf("%d",&n);
Scanf_Sq(Lb,n);
MergeList_Sq(L,Lb,Lc);
Printf_Sq(Lc);
DestroyList(Lb);
DestroyList(Lc);
printf("\n");
///测试前驱,后继
int pre_e,next_e,cur_e;
printf("请输入要判断前驱后继的cur_e:");
scanf("%d",&cur_e);
if( PriorElem(L,cur_e,pre_e) ) printf("%d的前驱是:%d\n",cur_e,pre_e);
else printf("该元素没有前驱\n");
if( NextElem(L,cur_e,next_e) ) printf("%d的后继是:%d\n",cur_e,next_e);
else printf("该元素没有后继\n");
/// 测试visit()
ListTraverse(L, visit);
Printf_Sq(L);
///测试Clear和Empty和Length和GetElem
int i;
printf("请输入i:");
scanf("%d",&i);
if( GetElem(L,i,e) ) printf("第%d个元素是%d\n",i,e);
else printf("该角标%d不在范围内\n",i);
printf("当前表长度为:%d\n",ListLength(L));
///测试union
InitList_Sq(&Lb);
printf("输入集合B的个数n:\n");
scanf("%d",&n);
Scanf_Sq(Lb,n);
union_Sq(L,Lb);
Printf_Sq(L);
printf("\n");
/// 测试MergeList
MergeList(L, Lb, Lc);
Printf_Sq(Lc);
///清空表
printf("下面进行清空表操作\n");
ClearList(L);
if(ListEmpty(L)) printf("L为空表\n");
else printf("L不是空表\n");
printf("\n");
DestroyList(L);
printf("TO BE END\n");
return 0;
}
///调试过程中出现了Bug
///DestroyList(Lb)和DestroyList(Lc)都出现了错误
///找了一番竟然是没有初始化,但是没初始化竟然能用,就是销毁的时候错了
///没初始化,L.elem里应该没有值吧,那就是越界访问了,if(L.elem)怎么又能进去呢
(数据结构第二章)线性表的实现
最新推荐文章于 2024-07-09 21:13:54 发布