// 顺序表2.cpp : 定义控制台应用程序的入口点。
//编译预处理:文件包含
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
//宏定义:预编译指令,定义符号常量,性能上没有常变量优越
#define LIST_INIT_SIZE 100//线性表存储空间的初始分配量
#define LIST_INCREMENT 10//线性表存储空间的分配增量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
//typedef为数据类型定义别名,此处可增强程序的可移植性
typedef int ElemType;
typedef int Status;//其值为函数结果状态码
//动态分配的顺序表类型定义
typedef struct
{
ElemType *elem;//定义存储空间基址指针
int length;//顺序表当前长度
int listsize;//顺序表当前分配的存储容量
}SqList;
//顺序表的初始化:
Status InitList_Sq(SqList &L)
{
L.elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));//线性表存储空间的初始分配量,这里没有指针域,所以为ElemType
if (!L.elem) exit(OVERFLOW);//存储分配失败
L.length = 0;//空表长度为0
L.listsize = LIST_INIT_SIZE;//初始化存储容量
printf("初始存储容量为:%d\t存储空间基址为:%d\n", L.listsize,*L.elem);
return OK;
}
//
//插入结点:1.插入位置合法性判断;2.存储空间内存是否已满判断;3.插入位置后的元素右移
//时间复杂度:o(n)
Status ListInsert_Sq(SqList &L, int i, ElemType e)//&不表示取地址,表引用,只在结构体发生了变化的情况下使用
{
ElemType *newbase;//用于存储新结点的存储单元地址
ElemType *p, *q;
if (i<1 || i>L.length + 1)//这里考虑在对应位置上放元素,可插入位置从第一个位置到最后一个位置+1,所以不需要考虑数组的0位置
return ERROR;
if (L.length >= L.listsize)//超过了当前分配的存储容量
{
newbase = (ElemType *)realloc(L.elem, (LIST_INIT_SIZE + LIST_INCREMENT) * sizeof(ElemType));
if (!newbase)
exit(OVERFLOW);
L.elem = newbase;//更新当前存储空间基址
L.listsize += LIST_INCREMENT;//增加存储空间容量
}
q = &(L.elem[i - 1]);//此处L.elem可近似看似数组的首地址,q为插入位置在内存单元中的地址
for (p = &(L.elem[L.length - 1]);p >= q;--p)//p为尾结点的地址
*(p + 1) = *p;//将p对应内存单元中的数据元素赋给p+1,即:数据元素右移
*q = e;//插入e
++L.length;//当前表长+1
return OK;
}
//删除结点:1.判断删除位置是否合法;2.删除位置后的元素左移
//时间复杂度:o(n)
Status ListDelete_Sq(SqList &L, int i, ElemType *e) {//e为指向ElemType类型的指针变量
ElemType *p, *q;
if (i<1 || i>L.length)
return ERROR;
p = &L.elem[i - 1];//取i-1位置的地址
e = p;
//q = L.length + L.elem - 1;
q = &(L.elem[L.length - 1]);
for (++p;p <= q;++p)
*(p - 1) = *p;
--L.length;//此处不释放内存单元是因为采用的是动态内存分配,下次使用时直接覆盖,所以不需要释放
return OK;
}
//按值查找位序:不断的将e与顺序表内的数据元素进行比较
//平均时间复杂度:O(n)
/*int LocateElem_Sq(SqList L, ElemType e)
{
int i = 0;
for (i = 0;i < L.length;i++)
if (e == L.elem[i])
return i + 1;
return ERROR;
}*/
Status compare(ElemType e1, ElemType e2)
{
if (e1 == e2) {
return OK;
}
else {
return ERROR;
}
}
int LocateElem_Sq(SqList L, ElemType e, Status(*compare)(ElemType, ElemType))//函数指针:Status表示函数指针变量compare所指向的函数的返回值类型,注意区分:Status *compare()表示compare是一个返回值为指针类型的函数
{
int i;
ElemType *p;
i = 1;
p = L.elem;
while (i <= L.length && !(*compare)(*p++, e))//*p++<==>*p;p=p+1;
++i;
if (i <= L.length)
return i;
else
return 0;
}
int TraverseList(SqList L) {/*L为顺序表*/
int i;
for (i = 0;i < L.length;i++)
printf("%d\t", L.elem[i]);
printf("\n");
return 1;//函数结束语句
}
void input_data(SqList &L)
{
int n, i;
ElemType elem;
printf("input the number of data:\n");
scanf("%d", &n);
printf("input the data:\n");
for (i = 1;i <= n;i++) {
scanf("%d", &elem);
ListInsert_Sq(L, i, elem);//L?
}
}
//将LA、LB归并为一个新的线性表LC,LC中的数据元素按值非递减有序排列
/*void MergeList_Sq(SqList La,SqList Lb,SqList *Lc)
{
ElemType *pa, *pb, *pc, *pa_last, *pb_last;
Lc->listsize = Lc->length = La.length + Lb.length;
pa = La.elem;
pb = Lb.elem;
pc = Lc->elem = (ElemType *)malloc(Lc->listsize * sizeof(ElemType));
if (!Lc->elem)
exit(OVERFLOW);//存储分配失败
pa_last = La.elem + La.length - 1;
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的剩余元素
{
pb = pa + 1;
if (*pa <= *pb)
*pc++ = *pa++;
}
while (pb <= pb_last)//*pc++ = *pb++;
{
pa = pb + 1;
if (*pb <= *pa)
*pc++ = *pb++;
}
}*/
//初始条件:顺序表已存在 操作结果:销毁线性表L
Status DestroyList(SqList &L)
{
free(L.elem);
L.length = 0;
L.listsize=0;
return OK;
}
//初始条件:顺序表已存在;操作结果:将L重置为空表
Status ClearList(SqList &L)
{
L.length = 0;
return OK;
}
//初始条件:线性表L已经存在;操作结果:若L为空表,返回TRUE,否则返回FALSE
Status ListEmpty(SqList L)
{
if (L.length == 0)
return TRUE;
else
return FALSE;
}
//初始条件:线性表L已存在;操作结果:返回L中数据元素的个数
int ListLength(SqList L)
{
return L.length;
}
//初始条件:线性表L已存在,1<=i<=ListLength(L);操作结果:用e返回L中第i个数据元素的值;
Status GetElem(SqList L, int i, ElemType *e)
{
if (i<1 || i>ListLength(L))
return ERROR;
e = &L.elem[i - 1];
//e = L.elem + i - 1;
return OK;
}
//特殊的自定义函数:负责协调组装其它函数;
//函数调用的三种类型:1.作为语句(完成一定操作);2.作为表达式的一部分;3.作为函数的实参被调用
//调用函数时,系统为函数的形参分配存储单元,实参和形参之间是一种单向传递关系,即:只将实参的值赋给形参,修改形参不影响实参
int main()
{
SqList L,LB,LC;//定义一个SqList类型的数据对象
ElemType elem;
int i;
printf("input the data of LA:\n");
InitList_Sq(L);//L表示结构体类型的变量,相当于变量a
input_data(L);
TraverseList(L);//每个函数在编译、连接后都会占用一段连续的内存单元,内存中存放函数代码的首地址称为入口地址
printf("the length of the sq:%d\n",ListLength(L));
//ClearList(L);
printf("input the data of LB:\n");
InitList_Sq(LB);//L表示结构体类型的变量,相当于变量a
input_data(LB);
TraverseList(LB);//每个函数在编译、连接后都会占用一段连续的内存单元,内存中存放函数代码的首地址称为入口地址
/* printf("input the value of i in the LA:\n");
scanf("%d", &i);
printf("input the elem of i in the LA:%d\n",GetElem(L,i,&elem));
printf("input the location of deleted elem in the LA:\n");
scanf("%d", &i);
ListDelete_Sq(L, i, &elem);//函数完成一定的操作,作为语句被调用,L?
TraverseList(L);
printf("input the elem of seeking in the LA:\n");
scanf("%d", &elem);
//printf("\n the location of elem in the table:%d\n", LocateElem_Sq(L, elem));
printf("\n the location of elem in the LA in the table:%d\n", LocateElem_Sq(L, elem, compare));//LocateElem_Sq()作为实参被调用,compare函数名代表了函数的入口地址,只需将函数名赋给函数指针变量
*/
/*printf("MergeList:\n");
MergeList_Sq(L, LB, &LC);*/
TraverseList(LC);
return 0;
}