18.12.23
#include<stdio.h>
#include<stdlib.h>
#define LIST_INITSIZE 100 //线性表存储空间的初始分配量
#define LIST_INCREMENT 10 //线性表存储空间空间的分配增量
#define OK 1
#define ERROR 0
#define OVERFLOW -1//溢出
typedef int ElemType; //设元素类型为int
typedef struct
{
ElemType *elem; //存储空间基址
int length; //当前长度
int listsize; //当前分配的存储容量 (以sizeof(ElemType)为单位)
}SeqList; //定义线性表的类型
int InitList (SeqList &L) //线性表的初始化,构造一个空的线性表L
/*形参L为引用型变量,&为取地址符(此处为引用传递),形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作。
用了引用变量后,就不再为形参开辟内存,所有操作都是直接修改实参变量。 */
{
L.elem = (ElemType *)malloc(LIST_INITSIZE * sizeof(ElemType));
if(! L.elem) // L.elem = NULL时,NULL(值为0)为空指针
exit(OVERFLOW); //存储分配失败,结束程序
L.length = 0; //空表长度为0
L.listsize = LIST_INITSIZE; //初始化存储容量
return OK;
}
int CreatList(SeqList &L)
{
int i;
scanf("%d",&L.length);
for(i = 0;i < L.length;++i)
{
scanf("%d",L.elem + i);
}
}
int InsertList(SeqList &L,int i,ElemType e)
{
//在顺序线性表L中第i个位置之前插入新的e
//i的合法值为1<=i<=L.length + 1
ElemType *newbase,*q,*p;
if(i<1 || i > L.length + 1)
return ERROR; //i的值不合法
if(L.length >= L.listsize) //当前存储空间已满,增加分配
{
newbase = (ElemType*)realloc(L.elem,(L.listsize + LIST_INCREMENT) * sizeof(ElemType));//重新分配存储空间
if(! L.elem)
exit(OVERFLOW);
L.elem = newbase; //新基址
L.listsize += LIST_INCREMENT; //增加存储容量
}
q = &(L.elem[i-1]); //q为插入的地址
for(p = &(L.elem[L.length - 1]);p >= q;--p) //p初始值为表尾元素的位置
*(p+1) = *p; //插入位置及之后的元素右移
*q = e; //插入e
++L.length; //表长增1
return OK;
}
int DeleteList(SeqList &L,int i,ElemType &e)//在顺序线性表L中删除第i个元素,并用e返回其值
{
ElemType *p,*q;
if(i<1 || i > L.length)
return ERROR; //i的值不合法
p = &(L.elem[i-1]); //p 为被删除元素的位置, p = L.elem + i - 1
e = *p; //被删除元素的值赋给e
q = L.elem + L.length - 1; //表尾元素的位置
for(++p;p <= q;++p) //p=p+1初始
*(p-1) = *p; //被删除元素之后的元素左移
--L.length; //表长减一
return OK;
}
/*
int Locate_List(SeqList L,ElemType e,int (*compare)(ElemType,ElemType))
//在顺序线性表L中查找第1个值与e满足compare()的元素的位序
//若找到,则返回其在L中的位序,否则返回0
{
int i;
ElemType *p;
i = 1; //i的初值为第1个元素的位序
p = L.elem; //p的初值为第1个元素的存储位置
while(i <= L.length && !(*compare)(*p++,e)) //*p++先以原值带入,compare为函数指针
++i; //遍历查找
if(i <= L.length)
return i--;
else
return 0;
}
*/
void MergeList(SeqList La,SeqList Lb,SeqList &Lc)
{
//已知顺序线性表La和Lb的元素按值非递减排列
//归并La和Lb得到新的顺序线性表Lc,Lc的元素也按值非递减排列
ElemType *pa,*pb,*pc,*pa_last,*pb_last;
pa = La.elem;
pb = Lb.elem;
Lc.listsize = Lc.length = La.length + Lb.length;
pc = Lc.elem = (ElemType *)malloc(Lc.listsize * sizeof(ElemType));
if(! Lc.elem) //存储分配失败
exit(OVERFLOW);
pa_last = La.elem + La.length - 1; //相当于&La.elem[La.length - 1],最后一个元素的存储位置
pb_last = Lb.elem + Lb.length - 1;
while(pa <= pa_last && pb <= pb_last)//归并,递增排列,其中一个顺序表插入完结束循环
{
if(*pa <= *pb) //小值先进
*pc++ = *pa++; //*(pc++) = *(pa++),先使用原值进行运算,相当于*pc = *pa,pc++,pa++
else
*pc++ = *pb++;
}
while(pa <= pa_last)
*pc++ = *pa++; //Lb先完全插入,之后插入La的剩余元素
while(pb <= pb_last)
*pc++ = *pb++; //La先完全插入,之后插入Lb的剩余元素
}
void Del_Repe(SeqList &L,SeqList &E) //删除有序顺序线性表(递增或递减)中重复元素,并返回其值
{
int i;
for(i = 1;i <= L.length -1;++i) //L.length 与Delete函数对应
{
if(L.elem[i-1] == L.elem[i])
{
DeleteList(L,i,*(E.elem+E.length));//调用删除函数,删除重复元素且表长减一
E.length++;
i--; //Delete函数时表长减一,i之后元素左移,需重新判断i上的数是否重复
}
}
}
void PrintList(SeqList L) //输出顺序线性表
{
int i = 0;
for(i = 0;i < L.length;++i)
printf("%d ",*L.elem++); //printf("%d",*L.elem),L.elem++,因为L是形参,L.elem自增不影响实参
printf("\n");
}
main()
{
SeqList La,Lb,Lc,E;
ElemType e;
int i;
InitList(La); //引用传递,函数内直接改变实参变量
InitList(Lb); //线性表的初始化,分配动态存储空间
InitList(E);
CreatList(La);
CreatList(Lb);
MergeList(La,Lb,Lc);
PrintList(Lc);
Del_Repe(Lc,E);
PrintList(Lc);
PrintList(E);
}