目录
线性表
定义:零个或多个数据元素的有限序列。
顺序存储结构
顺序表
1.顺序表存储结构
#include<stdio.h> #include<stdlib.h> #define MAXSIZE 20 //线性表存储空间的初始分配量 #define OK 1 //成功标识 #define ERROR 0 //失败标识 typedef int Status; //Status是函数的类型,其值是函数结果状态代码,如OK等 typedef int ElemType; //ElemType的类型根据实际情况而定 //顺序表数据结构 typedef struct { ElemType *elem; int length; }SqList;
2、构造一个空的顺序表L
①申请空间
②判断申请是否成功
③L -> length = 0;//构造空顺序表
Status InitList(SqList* L){ //构造一个空的线性表L L -> elem = (ElemType *)malloc(MAXSIZE*sizeof(ElemType)); if(!L -> elem){ return ERROR; } L -> length = 0; return OK; }
3、顺序表的插入
操作目的:在L中的第i个位置之前插入新的数据元素e,L的长度加1
①传入顺序表SqList *L(要加*:因为该操作要改变顺序表),第i个位置,要插入的新元素e
②判断该线性表的是否还有空间
③判断i在不在顺序表范围内
④若插入位置不在表尾,要对第i个元素及其后面的元素都进行移位操作
⑤将新元素插入第i个位置
⑥长度加1
Status ListInsert(SqList *L, int i, ElemType e){ int k; if (L->length == MAXSIZE){ //线性表没有剩余空间 return ERROR; } if (i < 1 || i > L->length+1){ //当i不在范围内时 return ERROR; } if (i <= L->length){ //若插入位置不在表尾 for(k = L->length-1;k >= i-1;k--){ L->elem[k+1] = L->elem[k]; } } L->elem[i-1] = e; //将新元素插入 L->length++; //长度加1 return OK; }
4、顺序表的删除
操作目的:删除L的第i个数据元素,并用e返回其值,L的长度减1
①传入顺序表SqList *L(要加*:因为该操作要改变顺序表),第i个位置,该位置元素值e
②判断顺序表是否为空以及i在不在顺序表范围内
③给e赋上该位置元素值
④如果删除位置不在最后位置,要把该位置后的元素全都向前移位
⑤长度减1
Status ListDelete(SqList *L, int i, ElemType *e){ int k; if(L->length == 0){ //线性表为空 return ERROR; } if(i < 1 || i > L->length){ //删除位置不正确 return ERROR; } *e = L -> elem[i-1]; if(i < L->length){ //如果删除位置不在最后位置 for(k = i;k < L->length;k++){ L->elem[k-1] = L->elem[k]; } } L->length--; //长度减1 return OK; }
5、获取顺序表某位置的元素
操作目的:用e返回L中第i个数据元素的值
①判断顺序表是否为空,以及i是否在顺序表中
②给e赋上该位置元素值
Status GetElem(SqList L, int i, ElemType *e){ if(L.length == 0 || i<1 || i>L.length){ return ERROR; } *e = L.elem[i-1]; return OK; }
6、读取顺序表所有元素
void OutPut(SqList L){ printf("当前顺序表的长度:%d\n", L.length); for(int i = 0; i < L.length; i++){ printf("%d ",L.elem[i]); } printf("\n"); }
7、主函数调用
int main() { SqList L; printf("------构造一个空的线性表L------\n"); InitList(&L); OutPut(L); //打印结果 printf("------测试插入10个数------\n"); for(int i = 1;i <= 10; i++){ ListInsert(&L,i,i); } OutPut(L); //打印结果 printf("------在第三位之前插入0------\n"); ListInsert(&L,3,0); OutPut(L); //打印结果 printf("------删除第6位的数据------\n"); ElemType e; ListDelete(&L,6,&e); printf("删除的数据为:%d\n", e); OutPut(L); //打印结果 printf("------获取元素操作------\n"); GetElem(L,5,&e); printf("得到第5个元素:%d", e); }
8、运行结果
9、优缺点
优点:空间利用率高
缺点:插入和删除操作需要移动大量元素
链式存储结构
单链表
1、说明:
首元节点:链表中存储第一个数据元素的节点
头节点:首元节点之前设置的节点
头指针:指向链表中第一个节点的指针
2、增设头节点的作用:
1、便于首元节点的处理
增加头节点之后,首元节点的地址保存在头节点的指针域中,则对链表第一个元素的操作和其他元素操作一样,无需进行特殊处理
2、便于空表和非空表统一处理
增设头节点后,无论链表是非为空,头指针都是指向头节点的非空指针
3、单链表的特点:
1、随机存储:
各个元素的存储位置是随意的
2、顺序存取:
单链表是非随机存取的存储结构,要取得第i个元素必须从头指针出发顺链表进行查找
具体操作:
1、定义链表
typedef struct node{ int data; //数据域 struct node *next;//指针域 }Lnode,*List;
2、初始化链表
status Init(list &L) { L=new node; L->next=NULL; return OK; }
3、创建链表
void creat(List &L,int n)//头插法 { L=new node; L->next=NULL;//创建只有一个空节点的新链表 for(int i=0;i<n;i++) { List p=new node;//生成一个新节点 cin>>p->data ;//给新节点赋值 p->next =L->next ;//将此元素插在头节点之后1 L->next =p;//将此元素插在头节点之后2 } }
void creat(List &L,int n)//尾插法 { L=new node; L->next=NULL;//创建只有一个空节点的新链表 list t=new node; t=L; for(int i=0;i<n;i++) { List p=new node;//生成一个新节点 cin>>p->data ;//给新节点赋值 p->next =NULL ; t->next =p;//将此节点插在尾节点之后 t=p;//位移,使t一直是最后一个节点 } }
4、取值
status get(List L,int i,int &e)//因为要给e赋值,即对e进行修改所有要加取地址符 { List p=new node; p=L->next ;//设置p为移动节点,协助查找第i个元素 int j=1;//计数 while(p&&j<i)//找到第i个位置的节点 { p=p->next ;//一直向后查找 j++; } if(!p||j<i)//p为空指针或者j<i返回查找失败 return ERROR; e=p->data ;//把该节点的数据赋给e return OK; }
5、查找
List find(List L,int e) { List p=new node; p=L;//移动节点p查找数据域为e的节点 while(p&&p->data !=e)//查找 { p=p->next ; } /*if(!p&&p->data !=e) return NULL;这句可以不用加,因为如果不符合条件,跳出循环后p即是NULL */ return p; }
6、插入
status Insert(List &L,int i,int e) { List p=new node;//设置p为移动节点,协助查找第i个元素 p=L; int j=0;//(为什么上面查找的时候j=1,这里却等于0呢)好好思考一下偶!! while(p&&j<i-1)//找到第i-1个节点 { p=p->next ; j++; } if(!p||j>i-1)//错误是返回插入失败 return ERROR; List t=new node;//开辟新结点便于插入 t->data =e;//给新结点赋值 t->next =p->next ;//指向第i个节点 p-next=t;//代替第i个节点的位置 return OK; }
7、删除
status Delete(List &L,int i) { List p=new node;//开辟新节点 p=L; int j=0;//计数 while(p&&j<i-1)//位移到j=i-1的位置 { p=p->next ; j++; } if(!p||j>i-1) return ERROR; p->next =NULL;//把第i个节点赋值为空 return OK; }