数据结构是相互之间一种或多种关系的数据元素的集合,它是针对具体的问题提出的,我们在分析问题的过程中一般要经历:根据问题建立数学模型(逻辑结构),在计算机中建立相应的存储结构,设计算法实现解决问题的方法。线性表是属于存储结构的一种基本类型。
一个问题可以通过一种逻辑结构表示,多种存储结构存储。下面我们讨论线性表的顺序存储和链式存储用类C语言的实现过程。
【顺序结构】
顺序结构是在计算机内部分配连续的内存单元,这些内存单元存放线性表的数据,同时这些内存单元都有内存地址来唯一标识。
下面实现线性表的定义和基本操作:
1. 线性表动态分配存储结构
线性表在内存中表示要有内存基址,在内存中占有总长度和存储容量。线性表的数据元素在内存中的表示要有初始化地址和增量,因此,在线性表定义时,首先定义初始地址分配量和内存增量。
#define LIST_INIT_SIZE 100 //线性表存储空间初始分配量
#define LISTNCREMENT 10 //线性表存储空间分配增量
Typedef struct{
ElemType *elem; //存储空间基地址
Int length ;//当前长度
Int listSize ; //当前分配存储容量
}SqList;
2. 初始化
初始化过程是在内存中分配空间,获得定义的数据值的初始值。
//初始化
Status InitList_sq(SqList &L){
L.elem=(ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
If(!L.elem) eixt(ERROR);
L.length=0;
L.listsize=LIST_INIT_SIZE;
Return OK;
}
3. 插入操作
插入操作必须指明在哪个线性表下的第几个元素前插入数据元素e,执行的操作首先判断指定位置是否越界,然后判断内存空间是否溢出,如果溢出则需要重新定义基址、修改内存容量。
//插入
Status ListInsert_Sq(SqlList &L,int I,elemtype &e){
If(i<1 || i>l.length) return ERROR;
If(L.size>L.length){
Newbase=(elemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(Elemtype));
If(!newbase) exit(ERROR);
L.elem=newbase;
L.listsize+=LISTINCREMENT;
}
q=&(L.elem[i-1]);
For(p=&(L.elem[L.length-1];p>=q;--p) *(p+1)=*p;
*q=e;
++L.length;
Return OK;
}
4.删除
//删除
Status ListDelete_sq(SqList &L,int I,ElemType &e){
If(i<1 || i>l.length) return ERROR;
p=&(L.elem[i-1]);
e=*p;
q=L.elem+L.length-1;
For(++p;p<=q;p++) *(p-1)=*p;
--L.length;
Return OK;
}
5. 合并
Void MergeList_Sq(SqList La,SqList Lb,SqList &Lc){
Pa=La.elem; pb=Lb.elem;
Lc.listSize=Lc.length=Lb.length+La.length;
Pc=Lc.elem=(ElemType *)malloc(Lc.listSize*sizeof(elemType));
If(!Lc.elem) exit(OVERFLOW);
Pa_last=La.length-1;
Pb_last=Lb.length-1;
While(pa<=pa_last && pb<=pb_last)
{
If(*pa<=*pb) *pc++=*pa++;
Else *pc++=*pb++;
}
While (pa<=pa_last) *pc++=*pa++;
While(pb<=pb_last) *pc++=*pa++;
}
【链表结构】
对比链表结构与顺序结构,链表结构减少了顺序结构在插入和删除过程的元素移动操作,但查询速度降低。代码实现过程如下:
c. 链表结构
//定义数据结构
Typedef struct Lnode{
ElmeType data;
Struct Lnode next;
}Lnode,*LinkList
//创建链表
Void CreateList_L(LinkList &L,int n){
L=(LinkList)malloc(sizeof(Lnode));
L.next=Null;
For(int i=0;i<n;++i){
p=(LinkList)malloc(sizeof(Lnode));
Scanf(&p->data);
p->next=L->next;
L->next=p->next;
}
}
//插入
Status ListInsert_L(LinkList L,int I,ElemType e){
p=L;int j=0;
While(p && j<i){
p=p->next;
}
If(!p || i>j) exit(ERROR);
s=(LinkList)malloc(sizeof(LinkList));
s->next=p->next;
s->data=e;
p->next=s;
Return OK;
}
//删除
Status ListDelete_L(LinkList L,int I,ElemType &e){
p=L; int j=0;
While(p && j>i){
p=p->next;
}
If(!p && j>i) exit(ERROR);
q=p->next;
}
//合并
Void MargeList_L(LinkList &La,LinkList &Lb,LinkList &Lc){
Pa=La->next; pb=Lb->next;
Pc=Lc=La;
While(pa && pb){
If(pa->data<pb->data){
Pc->next=pa->next;
Pc=pa;
Pa->next=pa->next;
}else{
Pc->next=pb->next;
Pc=pb;
Pb->next=pb->next;
}
}
Pc->next=pa?pa:pb;
Free(Lb);
}
【总结】
数据结构的学习让我们更加清楚的看到算法在内存中的存储过程,以及如何用代码的实现过程,并通过时间和空间复杂性讨论算法的优劣。