#include <stdio.h>
#include <stdlib.h>
#define LIST_INIT_SIZE 100;
#define LISE_INCREMENT 10;
//定义一个枚举常量,默认no = 0, ok = 1
enum Status{no, ok};
typedef struct Sqlist
{
//数组元素类型是整型
int *elem;//指针指向线性表的基地址,即数组名,数组的第一个元素的地址。
//实质上,用一个指向首地址的指针代表了数组
int length;//顺序表的实际元素个数,当前长度
int listsize;//顺序表当前预分配的存储空间,预定义大小
}Sqlist;
//顺序表的初始化操作,就是为顺序表分配一个预定义大小的数组空间,
//并将线性表的当前长度设为‘0’,意思是当前数组中有0个元素。
//已经为数组分配了一定的内存空间,只是里面没放东西而已。
//实质上,就是定义一个变长数组。
//&L是一个地址,实质上是一个结构体的首地址,也就是用指针指向结构体首地址代表一个顺序表
Status InitList_Sq(Sqlist &L)
{
//给结构体中的基地址赋值,类似于给数组的首地址赋值
//构造一个空的线性表,预分配100存储空间
L.elem = (int *)malloc(LIST_INIT_SIZE * sizeof(int));
if(!elem)//在一个指针前加"!"运算符,表示该指针值与NULL相等,即P==NULL,也就是指针为空,或指针不存在
return no;
//下面两行,定义了一个有0个元素,但是占有100个空间的空表(空数组)
L.length = 0;
L.listsize = LIST_INIT_SIZE;
return ok;
}
//顺序表的插入操作,主要是第n至i(共n-i+1)个元素依次后移动一个位置
Status ListInsert_Sq(Sqlist &L, int i, int e)
{//在顺序线性表L中第i个位置之前插入新的元素e
//i的合法值为1<=i<=List_length + 1
if(i < 1 || i > L.length+1)
return no;
//若当前存储空间已满,增加分配
if(L.length > L.listsize)
{
//realloc函数用来修改原指针所指向的对象的长度。
int *new = (int *)realloc(L.elem,
(LIST_INIT_SIZE + LISE_INCREMENT) * sizeof(int));
if(!new)//存储分配失败
return no;
L.elem = new;//新基址
L.listsize += LISE_INCREMENT;//增加存储容量
}
int *q;//q为插入位置
q = &(L.elem[i-1]);
for(p=&(L.elem[L.length-1]); p>=q; ++p)
*(p+1) = *p;//插入位置及之后的元素右移动
*q = e;//插入e
++L.length;//元素个数增1
return ok;
}
#include <stdio.h>
#include <stdlib.h>
#define INIT_LIST_SIZE 100
#define LISTINCREMENT 10
enum Status {no, ok};
//定义一个顺序表的结构体
typedef struct
{
int *a;//顺序表中的基地址,
int len;
int size;
}Sqlist;
Status Init_SqList(Sqlist &L)
{
L.a = (int *)malloc(INIT_LIST_SIZE * sizeof(int));
if(L.a == NULL)
return no;
L.len = 0;//有0个元素
L.size = INIT_LIST_SIZE;//顺序表预设的空间
return ok;
}
Status Insert_Sqlist(Sqlist &L, int i, int e)
{
if(i < 1 || i > L.len + 1)
return no;
if(L.len >= L.size)//当存储空间已满的时候,重新分配
{
int *new = (int *)realloc(Sqlist &L,
(INIT_LIST_SIZE + LISTINCREMENT) * sizeof(int));
if(!new)
return no;
L.a = new;
L.size += LISTINCREMENT;
}
int *loc, *p;//loc为插入位置,p为操作指针
loc = &(L.a[i-1]);
for(p = &(L.a[len - 1]); p >= loc; --p)
*(p+1) = *p;//移动元素的操作-
*loc = e;//插入e
++L.len;//表长增1
return ok;
}
顺序表插入运算步骤总结:
1, 初始化一个空顺序表
2, 判断插入位置是否合法
3, 若表满,分配新的空间,已被移动元素后,能在表中腾出位置以供插入
4, 从表尾依次移动元素,在待插入位置腾出一个空位
5, 插入元素
6, 表长增1.
//在顺序表中删除第i个元素
Status Delete_Sqlist(Sqlist &L, int i, int &e)
{
int *p;//待删除元素
int *q;//表尾元素
//判断删除位置是否合法
if(i < 1 || i > L.len)
return no;
p = &(L.a[i-1]);//待删除元素的位置,也可写成 L.a + i - 1
e = *p;
q = L.a + L.len - 1;//表尾元素的位置,也可写成 &(L.a[len - 1])
for(p; p <= q; ++p)
*(p-1) = *p;//移动元素的操作
--L.len;//表长也要变化
return ok;
}
顺序表删除元素运算总结:
1, 判断删除位置是否合法
2, 将操作指针p指向待删除的元素的存储位置
3, 将待删除元素的值取出,复制给e
4, 确定表尾元素的存储位置。
5, 循环处理操作指针P,移动元素,将后一项赋值给前一项,删除待删元素
6, 表长减1
//顺序表合并
Status Merge_Sqlist(Sqlist La, Sqlist Lb, Sqlist &Lc)
{
//已知顺序表La,Lb的元素按值非递减排列
//归并La和Lb得到新的顺序线性表Lc,Lc的元素也按值非递减排列
int *pa, int *pb, int *pc;
int *pa_Last, *pb_Last;
pa = La.a;//指向La首地址的指针pa
pb = Lb.a;//指向Lb首地址的指针pb
Lc.size = Lc.len = La.len + Lb.len;//Lc的长度应该是La与Lb之和
//指向Lc首地址的指针pc
pc = Lc.a = (int *)malloc(Lc.size * sizeof(int));//创建Lc的存储空间
if(!pc)
return no;
pa_Last = La.a + La.len - 1;//La最后一个元素的存储地址
pb_Last = Lb.a + Lb.len - 1;//Lb最后一个元素的存储地址
//La与Lb都没有取完的情况下
while(pa <= pa_Last && pb <= pb_Last)
{
if(*pa <= *pb)
*pc++ = *pa++;\\等价于:*pc = *pa; pa++; pc++;
else
*pc++ = *pb++;
}
//Lb已经取完,只取La元素的情况下
while(pa <= pa_Last)
*pc++ = *pa++;
//La已经取完,只取Lb元素的情况下
while(pb <= pb_Last)
*pc++ = *pb++;
return ok;
}
两个有序顺序表合并的运算总结:
1,先设置两个操作指针pa,pb,分别指向已有顺序表La,Lb的首地址。
2,再定义两个指针pa_Last,pb_Last,分别指向已有顺序表La,Lb的表尾地址,
以便于判断pa,pb是否滑动到La,Lb表尾。
3,通过初始化pc指针的方式来定义Lc顺序表,预先给Lc开辟长度为La.len + Lb.len的空间。
4,La与Lb都没有取完的情况下,通过比较取得两个表中元素的较小者,放入Lc中。
5,Lb已经取完,只取La元素并将其放到Lc中。
6,La已经取完,只取Lb元素并将其放到Lc中。