目录
1.线性表的定义与操作
LinearList(线性表)的部分数据运算:
Initsist(&L)//初始化表
DestroyList(&L)//销毁操作
ListInsert(&L,i,e)//插入操作。在表L第i个位置(位序)插入元素e
ListDelete(&L,i,&e)//删除操作。删除表L第i个位置,用e返回删除元素的值
LocateElem(L,e)//按值查找
GetElem(L,i)//按位查找(位序)
Length(L)//求表长
PrintList(L)//输出操作,打印表
Empty(L)//判空操作 。L空——true
所有命名都采用驼峰命名法
2.顺序表
2.1顺序表的定义
2.1.1静态分配实现顺序表
sequence list
分配的存储空间大小为:MaxSize*sizeof(ElemType)
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];//用静态数组存放数据元素 (于存储空间是静态的,表长刚开始确定后就无法更改)
int length;
}SqList;
没有设置数据默认值时违规打印顺序表时,出现了脏数据
静态分配实现过程:
#include <stdio.h>
#define MaxSize 10
typedef struct{
int data[MaxSize];//用静态数组存放数据元素 (由于存储空间是静态的,表长刚开始确定后就无法更改)
int length;
}SqList;
void InitList(SqList &L){
L.length = 0;//初始化顺序表表长为0
}
void PrintList(SqList L){
int i;
for(i=0;i<L.length;i++){ //其实这里用L.length访问元素也是不友好的 而是用GetELEM(L)这一基本操作来访问各个数据元素
printf("data[%d] = %d\n" , i , L.data[i]);
}
}
int main(){
SqList L;
InitList(L);
//...
PrintList(L);
}
2.1.2动态分配实现顺序表
#define InitSize 10
typedef struct{
ElemType *data;//指示动态分配数组的指针
int MaxSize; //顺序表最大长度
int length;//顺序表当前长度
}SeqList;
//C——malloc free 函数 stdlib.h中有定义
L.data = (ElemType*) malloc(sizeof(ElemType) * InitSize);//分配连续的内存空间 要强制转换类型
//C++——new delete 关键字
//eg 申请分配10个int型数据的一片连续空间(10*4B),并用L.data返回该存储空间的首地址(指针),并对该指针强转
L.data = (int*) malloc(sizeof(int) * InitSize);
动态分配实现过程:
#include <stdlib.h>//mallo free 函数的头文件
#define InitSize 10
//顺序表的定义
typedef struct{
int *data;//指示动态分配数组的指针
int MaxSize; //顺序表最大长度
int length;//顺序表当前长度
}SeqList;
//初始化操作
void InitList(SeqList &L){
L.data = (int*) malloc(sizeof(int) * InitSize); //用malloc申请一篇连续空间 (动态数组)
L.length = 0;
L.MaxSize = InitSize;
}
//增加动态数组长度的操作
void IncreaseList(SeqList &L,int len){
//step1:用p指向原存储空间
int *p = L.data;
//step2:用L.data指向malloc开辟InitSize+len的新空间
L.data = (int*) malloc(sizeof(int) * (InitSize+len));
//step3:原空间向新空间复制(时间开销很大)
for(int i=0;i<L.length;i++){
L.data[i] = p[i];//依然可以用下标法访问
}
//step4:修改L.MaxSize
L.MaxSize = L.MaxSize+len;
//step5:释放p
free(p);
}
int main(){
SeqList L;//声明一个顺序表 存储了*data length MaxSize 三个变量
InitList(L);
//...
IncreaseList(L,5);//增加动态数组的长度
}
2.2顺序表的插入和删除
2.2.1顺序表的插入
示例:在表L的第3个位置插入元素9
#include<stdio.h>
#define MaxSize 5
typedef struct{
int data[MaxSize];
int length;
}SqList;
void InitList(SqList &L){
L.length = 0;
}
bool ListInsert(SqList &L,int i,int e){//在表L的第i个位置插入元素e
//step1、2使算法更具有健壮性
// //step1:存储空间满的判断
// if(L.length>=MaxSize){
// printf("L is full\n");
// return false;
//
// }
// //step2:插入的合法性判断,0<i<=length时有效
// if(i<1 || i>L.length+1){
// printf("invalid i\n");
// return false;
// }
//step1:存储空间满的判断
if(L.length>=MaxSize)
return false;
//step2:插入的合法性判断,0<i<=length时有效
if(i<1 || i>L.length+1)
return false;
//step3:从尾部(length-1的位置)移
for(int j=L.length;j>=i;j--){
L.data[j] = L.data[j-1];
}
//step4:插
L.data[i-1] = e;
//step5:改(表长+1)
L.length++;
return true;
}
void PrintList(SqList L){
printf("L中数据如下:\n");
for(int i=0;i<L.length;i++){ //其实这里用L.length访问元素也是不友好的 而是用GetELEM(L)这一基本操作来访问各个数据元素
printf("data[%d] = %d\n" , i , L.data[i]);
}
printf("\n");
}
int main(){
SqList L;
InitList(L);
for(int i=0,j=1;i<3;i++,j++){//原表数据是这样子的,先假设原先插入了3个数据
ListInsert(L,j,i);
}
printf("原表length:%d\n",L.length);
PrintList(L);//未插入前打印一次
ListInsert(L,3,9);//在表L的第3个位置插入元素9
PrintList(L);//插入后打印一次
// 错误示例
// ListInsert(L,9,9);//在表L的第3个位置插入元素9:invalid i
}
动态分配方式下的插入操作代码同上
插入操作算法时间复杂度:最好O(1);最坏O(N);平均O(N)
2.2.2顺序表的删除
示例:删除表中第2个元素,用变量e带回(所以用引用类型&)
bool ListDelete(SqList &L,int i,int &e){
//step1:删除的合法性判断,0<i<=length时有效
if(i<1 || i>L.length) return false;
//step2:用e保留删除的元素,并返回
e = L.data[i-1];
//step3:从第i+1个向前移动
for(int j=i;j<L.length;j++){
L.data[j-1] = L.data[j];
}
//step4:改(表长-1)
L.length--;
return true;
}
int main(){
SqList L;
InitList(L);
for(int i=0,j=1;i<3;i++,j++){//原表数据是这样子的,先假设原先插入了一些数据
ListInsert(L,j,i);
}
printf("原表length:%d\n",L.length);
int e = -1;//???用e把删除的元素带回来
PrintList(L);//删除前打印一次
ListDelete(L,2,e) ;//删除data[1]
printf("删除的元素是:%d\n",e);
PrintList(L);//删除后打印一次
}
动态分配方式下的删除操作代码同上
删除操作算法的时间复杂度:最好O(1);最坏O(N);平均O(N)
2.3顺序表的查找
2.3.1按位查找
静态分配方式下实现顺序表的按位查找
示例:找到L第i个(位序)元素
#include<stdio.h>
#define MaxSize 10
typedef struct{
int data[MaxSize];//静态分配方式下
int length;
}SqList;
int GetElem(SqList L,int i){
return L.data[i-1];//随机存取的优势
}
int main(){
SqList L;
int check_i = 3;
InitList(L);
for(int i=0,j=1; i<5 ;i++,j++){//假设表中原有5个数据
ListInsert(L,j,i);
}
PrintList(L);
printf("查找到第%d个元素是:%d\n",checki,GetElem(L,check_i));
}
动态分配方式下的按位查找操作代码同上,也是用下标法访问表中元素,代码如下:
#include<stdio.h>
#include<stdlib.h>
#define InitSize 10
typedef struct{
int *data;//静态分配方式下
int length;
int MaxSize;
}SqList;
void InitList(SqList &L){
L.data = (int*)malloc(sizeof(int)*InitSize);
L.MaxSize = InitSize;
L.length = 0;
}
bool ListInsert(SqList &L,int i,int e){
if(L.length>= L.MaxSize) return false;
if(i<1 || i>L.length+1) return false;
for(int j=L.length; j>=i;j--){
L.data[j] = L.data[j-1];
}
L.data[i-1] = e;
L.length++;
return true;
}
void PrintList(SqList L){
printf("L中数据如下:\n");
for(int i=0;i<L.length;i++){ //其实这里用L.length访问元素也是不友好的 而是用GetELEM(L)这一基本操作来访问各个数据元素
printf("data[%d] = %d\n" , i , L.data[i]);
}
printf("\n");
}
int GetElem(SqList L,int i){
return L.data[i-1];//动态分配方式下也用下标法访问
}
int main(){
SqList L;
int check_i = 3;
InitList(L);
for(int i=0,j=1; i<5 ;i++,j++){//假设表中原有5个数据
ListInsert(L,j,i);
}
PrintList(L);
printf("查找到第%d个元素是:%d\n",checki,GetElem(L,check_i));
}
按位查找时间复杂度:最好/最坏/平均:O(1) //随机存取特性
2.3.2按值查找
示例:查找L中值为e的元素,返回其位序
#include<stdlib.h>
#include<stdio.h>
#define InitSize 10
typedef struct{
int *data;
int length;
int MaxSize;
}SeqList;
//查找值为e的元素,返回其位序
int LocateElem(SeqList L,int e){
for(int i=0;i<L.length;i++){
if(L.data[i] == e) return i+1;//注意位序和索引下标的关系
}
return 0;
}
int main(){
SeqList L;
int check_e = 4;
InitList(L);
for(int i=0,j=1; i<5 ;i++,j++){//假设表中原有5个数据
ListInsert(L,j,i);
}
PrintList(L);
printf("值为%d的元素在L中第%d个位置\n",check_e,LocateElem(L,check_e));
}
按值查找时间复杂度:最好O(1);最坏O(n);平均O(n)
3.单链表
3.1单链表的定义
3.1.1定义与重命名
struct LNode{ //定义单链表中的单个节点类型
ElemType data; //数据域 每个节点存放一个数据元素
struct LNode *next; //指针域 指向单链表中下一个节点
};
若要增加一个节点则用malloc实现:
struct LNode *p = (struct LNode *)malloc(sizeof(struct LNode));//默认乘 1
重命名
为了提升代码的可读性,在之后增加节点时可以用别名来写
typedef 该关键字 用于重命名数据类型 语法为:typedef <数据类型名> <别名>
eg:typedef <int> <zhengshu> 把int型重命名为“整数”类型(hhh为了提升代码可读性,