线性表
1.A=A并B
思路:1.从线性表LB中依次取得每个数据元素;
GetElem(LB, i)→e
2.依值在线性表LA中进行查访;
LocateElem(LA, e, equal( ) )
3. 若不存在,则插入之。
ListInsert(LA, n+1, e)
算法实现:
void union(List &La, List Lb)
{ // 将所有在线性表Lb中但不在La中的数据元素插入到La中
La_len = ListLength(La);
Lb_len = ListLength(Lb); // 求线性表的长度
for (i = 1; i <= Lb_len; i++)
{
GetElem(Lb, i, e); // 取Lb中第i个数据元素赋给e
if(!LocateElem(La, e) )
ListInsert(La, ++La_len, e); // La中不存在和 e 相同的数据元素,则插入之
}
}
2.线性表的合并问题
算法基本思路:1初始化 LC 为空表;
2分别从 LA和LB中取得当前元素 ai 和 bj ; GetElem(La, i, ai); GetElem(Lb, j, bj);
3若 ai≤bj,则将 ai 插入到 LC 中,否则将 bj 插入到 LC 中;ListInsert(Lc, ++k, ai); ListInsert(Lc, ++k, bj);
4重复 2 和 3 两步,直至 LA 或 LB 中元素 被取完为止;
5将 LA 表或 LB 表中剩余元素复制插入到LC 表中。
void MergeList(List La,List Lb,List &Lc){
//已知线性表La和Lb中的数据元素按值非递减排列
//归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列
InitList(Lc);//初始化
i=j=1;k=0;//计数第几个元素,位置从1开始,k用于Lc的计数
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(Lc,++k,ai);//ai插入Lc中
++i;
}
else{
ListInsert(Lc,++k,bj);
++j;
}
while(i<=La_len){
GetElem(La,i++,ai);//b表被扫完了a复制到c中
ListInsert(Lc,++k,ai);
}
while(i<=Lb_len){
GetElem(Lb,j++,bj);
ListInsert(Lc,++k,bj);
}
}
}//MergeList
3.线性表的顺序存储结构定义和表示
用物理位置来表示逻辑结构。
LOC(ai+1)=LOC(ai)+l ;
LOC(ai)=LOC(a1)+(i-1)*l
4.构造线性空表
Status InitList_Sq(SqList &L){
//构造一个空的线性表L
L.Elem =(ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
//malloc动态分配内存L括号里表示存放多少个元素
//E括号里表示每一个元素的存放类型
if(!L.Elem)exit(OVERFLOW)//存储分配失败
L.length=0;//空表长度 结构体变量取成员变量
L.listsize=LIST_INIT_SIZE;//初始存储容量
return ok;
}//InitList_Sq
malloc:
如果分配成功:则返回指向被分配内存空间的指针
不然返回指针NULL
同时,当内存不再使用的时候,应使用free()函数将内存块释放掉。
关于:void*,表示未确定类型的指针,c,c++规定void*可以强转为任何其他类型的指针,关于void还有一种说法就是其他任何类型都可以直接赋值给它,无需进行强转,但是反过来不可以
malloc:
malloc分配的内存大小至少为参数所指定的字节数
malloc的返回值是一个指针,指向一段可用内存的起始位置,指向一段可用内存的起始地址,多次调用malloc所分配的地址不能有重叠部分,除非某次malloc所分配的地址被释放掉malloc应该尽快完成内存分配并返回(不能使用NP-hard的内存分配算法)实现malloc时应同时实现内存大小调整和内存释放函数(realloc和free)
malloc和free是配对的,如果申请后不释放就是内存泄露,如果无故释放那就是什么也没做,释放只能释放一次,如果一块空间释放两次或者两次以上会出现错误(但是释放空指针例外,释放空指针也等于什么也没做,所以释放多少次都是可以的。)
原文链接:https://blog.csdn.net/flowing_wind/article/details/81240910
5.线性表顺序存储结构的C语言定义
//线性表的动态分配顺序存储结构
#define LIST_INIT_SIZE 100//线性表存储空间的初始分配量
#define LISTINCREMENT 10//线性表存储空间的分配增量
typedef struct{//结构体数据类型
ElemType *elem;//存储空间基址指向线性表占用的数组空间
int length;//线性表当前长度
int listsize;//当前分配的存储容量以sizeof(ElemType)为单位
}SqList;
6.线性表的顺序表插入操作
算法的基本思想:1检查i值是否超出所允许的范围(1≤i≤n+1),若超出,则进行“超出范围”错误处理;
2存储空间是否已满,如满需要增加空间;
3将线性表的第i个元素和它后面的所有元素均向后移动一个位置;
4将新元素写入到空出的第i个位置上;
5使线性表的长度增1。
Status InitList_Sq(SqList &L,int i,ElemType){
//在顺序线性表L中第i个位置之前插入新的元素e
//i的合法值为[1,n+1]
if(i<1||i>L.length+1) return ERROR;//i的值不合法
if(L.length>=L.listsize){//当前存储空间已满增加分配
newbase=(ElemType *)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof(ElemType));
//新地址
if(!newbase)exit(OVERFLOW);//存储分配失败
L.elem=newbase;//新基址
L.listsize+=LISTINCREMENT;//增加存储容量
}
q=&(L.elem[i-1]);//q为插入位置
for(p=&(L.elem[L.length-1]);p>=q;--q) *(p+1)=*p;
//插入位置及之后的元素右移
*q=e;
++L.length;//表长+1
return OK;
}//InitList_Sq
//插入从n开始,删除从i开始
realloc:
一、基本特性
1、 realloc()函数可以重用或扩展以前用malloc()、calloc()及realloc()函数自身分配的内存。
2、 realloc()函数需两个参数:一个是包含地址的指针(该地址由之前的malloc()、calloc()或realloc()函数返回),另一个是要新分配的内存字节数。
3、 realloc()函数分配第二个参数指定的内存量,并把第一个参数指针指向的之前分配的内容复制到新配的内存中,且复制的内容长度等于新旧内存区域中较小的那一个。即新内存大于原内存,则原内存所有内容复制到新内存,如果新内存小于原内存,只复制长度等于新内存空间的内容。
4、realloc()函数的第一个参数若为空指针,相当于分配第二个参数指定的新内存空间,此时等价于malloc()、calloc()或realloc()函数。
5、如果是将分配的内存扩大,则有以下3种情况:
5.1 如果当前内存段后面有需要的内存空间,则直接扩展这段内存空间,realloc()将返回原指针。
5.2 如果当前内存段后面的空闲字节不够,那么就使用堆中的第一个能够满足这一要求的内存块,将目前的数据复制到新的位置,并将原来的数据块释放掉,返回新的内存块位置。
5.3 如果申请失败,将返回NULL,此时,原来的指针仍然有效。
二、注意事项
1、第一个参数要么是空指针,要么是指向以前分配的内存。如果不指向以前分配的内存或指向已释放的内存,结果就是不确定的。
2、 如果调用成功,不管当前内存段后面的空闲空间是否满足要求,都会释放掉原来的指针,重新返回一个指针,虽然返回的指针有可能和原来的指针一样,即不能再次释放掉原来的指针。
平均移动次数:
7.线性表的顺序表删除操作
算法的基本思想:1检查i值是否超出所允许的范围(1≤i≤n),若超出,则进行“超出范围”错误处理;
2将线性表的第i个元素给e;
3将线性表的第i个元素后面的所有元素均向前移动一个位置;
4使线性表的长度减1。
Status InitList_Sq(SqList &L,int i,ElemType){
//在顺序线性表L中第i个位置之前插入新的元素e
//i的合法值为[1,n+1]
if(i<1||i>L.length+1) return ERROR;//i的值不合法
if(L.length>=L.listsize){//当前存储空间已满增加分配
p=&(L.elem[i-1]);//p为被删除元素的位置
e=*p;//被删除元素的值赋给e
q=L.elem+L.length-1;//表尾元素的位置
for(++p;p<=q;++p) *(p-1)=*p;
//插入位置及之后的元素左移
--L.length;//表长-1
return OK;
}//ListDelete_Sq
平均移动次数:
8.线性表的顺序表查找操作
int LocateElem_Sq(SqList L, ElemType e)
{// 在顺序表中查询第一个满足判定条件的数据元素
int i ; // 若存在,则返回它的位序,否则返回 0
i= 1;// i 的初值为第 1 元素的位序
p=L.elem;//p的初值为第 1 元素的存储位置
while (i <= L.length && L.elem[i-1]!=e)
++i;
if (i <= L.length) return i;
else return 0;
} // LocateElem_Sq
时间复杂度O(La.length*Lb.length)
9.线性表的合并问题
算法基本思路:1初始化 LC 为空表;
2分别从 LA和LB中取得当前元素 ai 和 bj ;
3若 ai≤bj,则将 ai 插入到 LC 中,否则将 bj 插入到 LC 中;
4重复 2 和 3 两步,直至 LA 或 LB 中元素 被取完为止;
5将 LA 表或 LB 表中剩余元素复制插入到LC 表中。
Void MergeList(SqList La, SqList Lb, SqList &Lc){
//已知线性表La和Lb中的数据元素按值非递减排列
//归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列
pa=La.elem;pb=Lb.elem;//LA,LB首递值
Lc.listsize=Lc.length=La.length+ Lb.length;
pc=Lc.elem=(ElemType*)malloc(Lc.listsize*sizeof(ElemType));
If(!Lc->elem) exit(overfiow);
pa_last=La.elem+La.length-1;
pb_last=Lb.elem+Lb.length-1;//la,lb最后位置
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的剩余元素
}//MergeList_Sq
时间复杂度O(nlogn)
10.顺序存储结构的优缺点
优点
逻辑相邻,物理相邻
可随机存取任一元素
存储空间使用紧凑
缺点
插入、删除操作需要移动大量的元素
预先分配空间需按最大空间分配,利用不充分
表容量难以扩充
11.结构体
一、结构体变量的定义
1.结构体类型与结构体变量分开定义
一般形式如下:
struct<结构体名><结构体变量名>;
eg:struct student student1,student2;
关键字struct要与结构体名student一起使用,共同构成结构体类型名
2.结构体类型与结构体变量同时定义
一般形式如下:
struct<结构体名>
{
<成员列表>
}<结构体变量名>;
3.无名结构体与结构体变量同时定义
一般形式如下:
struct
{
<成员列表>
}<结构体变量名>;
由于这里省略了结构体名,没有完整的结构体类型名,所以不能在其他位置再定义此结构体类型的变量
4.使用typedef为已有结构体类型取“别名”
一般形式如下:
typedef struct
{
<成员列表>
}<别名>;
这里的别名就相当于结构体类型名,之后就可以使用它定义结构体变量了
eg:
typedef struct
{
<成员列表>
}STU;
STU student1,student2;
那么这里就定义了俩个结构体变量student1,student2
二、结构体引用
1.通过“ · ”引用
结构体变量名.成员名
注:注意结构体变量名与成员名之间有点
2.通过“->”引用
结构体指针变量名->成员名
原文链接:https://blog.csdn.net/qq_37120369/article/details/81509443
【结构体参数调用归纳】
1)结构体变量作为函数参数[实参与形参]时,形参结构体变量成员值的改变不影响对应的实参构体变量成员值的改变。
2)结构体数组或结构体指针变量作为函数参数[实参与形参]时,形参结构体数组元素[或形参结构体指针变量指向的变量]成员值的改变将影响对应的实参构体数组[或实参结构体指针变量指向的变量]成员值的改变。
3)结构体变量可作为函数的参数,函数可返回一结构体类数据
4)p=&b; 使结构体指针变量p指向结构体变量b的空间。
p->num:表示通过指针变量引用结构体变量b的成员num
5)p=a;或p=&a[0];将结构体指针变量指向结构体数组a。则:
①p->num:表示通过指针变量引用结构体数组元素的成员num的值。
②p->num++:表示通过指针变量先引用结构体数组元素的成员num的值,再使该元素的成员num的值加 1,先引用其值然后其加1。
③++p->num:表示使指向的元素的成员num的值加1,再引用其值。
6)p=a;或p=&a[0];表示将结构体指针变量p指向结构体数组a。
①(p++)->num:表示通过指针变量先引用结构体数组元素 的成员num的值,再使指针变量本身加1,指针变量加1表示使指针变量指向结构体数组的下一个元素。
②(++p)->num:先使指针变量本身加1,先使使指针变量指向结构体数组的下一个元素,然后引用指针变量所指向的结构体数组元素的成员num的值。
原文链接:https://blog.csdn.net/tham_/article/details/45370607