线性表定义
线性表顾名思义就是具有线一样性质的表,即:零个或多个数据元素的有限序列。比如一个班学生的学号,有一个起始的学号,有一个收尾的学号,每一个都知道他前面的和他后面的,如同线一样把全班的串起来。
特别需要强调的:
1.元素个数有限且元素间有顺序。
2.第一个元素无前驱,最后一个元素无后继,其他每个元素有且只有一个前驱和后继。
线性表基本操作
initLis(*L):初始化操作,建立一个空的线性表L。
isEmpty(L):若线性表为空,返回true,否则返回false。
clearList(*L):清空线性表。
getElem(L,i):返回线性表中的第i个元素。
findElem(L,e):在线性表中查找元素e,若e存在就返回e在线性表中的位置,否则就返回-1。
insertElem(*L,i,e):在线性表中第i个位置插入元素e。
deleteElem(*L,i):删除线性表中的第i个元素。
listLength(L):返回线性表的元素个数。
线性表的顺序存储结构
顺序存储定义
用一段地址连续的存储单元依次存储线性表中的数据元素。
看到上图,用什么存储大概已经了然于胸了。对,没错。很容易就想到了用数组来实现。
顺序存储实现
#include<stdio.h>
#define MAXLEN 10
typedef int elemType;
typedef struct{
elemType data[MAXLEN];
int length;
}SqList;
void initList(SqList *L) //初始化线性表
{
for(int i=0;i<MAXLEN;i++)
L->data[i] = 0;
L->length = 0;
}
bool isEmpty(SqList L) //判断线性表是否为空
{
if(L.length == 0) return true;
return false;
}
elemType getElem(SqList L,int i) //根据位置得到线性表中的元素
{
if(L.length==0 || i<1 || i>L.length)
return -1;
return L.data[i-1];
}
bool insertElem(SqList *L,int i,elemType e) //在线性表的指定位置插入元素
{
int k;
if(L->length == MAXLEN)
return false;
if(i<1 || i>L->length+1)
return false;
if(i<=L->length)
{
for(k=L->length;k>=i-1;k--)
{
L->data[k+1]=L->data[k];
}
}
L->data[i-1]=e;
L->length++;
return true;
}
int findElem(SqList L,elemType e) //在线性表中查找元素
{
int i;
for(i=1;i<=L.length;i++)
if(getElem(L,i)==e) return i;
return -1;
}
bool deleteElem(SqList *L,int i) //删除第i个位置的元素
{
int k;
if(L->length==0)
return false;
if(i<1 || i>L->length)
return false;
if(i<L->length)
{
for(k=i;k<L->length;k++)
{
L->data[k-1]=L->data[k];
}
}
L->length--;
return true;
}
bool clearList(SqList *L) //清空线性表
{
bool ok = false;
int i,len;
len=L->length;
for(i=1;i<=len;i++)
ok = deleteElem(L,1);
return ok;
}
int main()
{
SqList L;
initList(&L);
for(int i=1;i<=10;i++)
if(insertElem(&L,i,i));
deleteElem(&L,2);
printf("%d\n",findElem(L,2));
printf("%d\n",getElem(L,2));
clearList(&L);
printf("%d",L.length);
return 0;
}
顺序存储的优缺点
优点:可以快速存取表中的任意元素。
缺点:1.插入和删除操作时需要移动大量元素。
2.长度变化较大时,难以确定存储空间容量。
3.容易造成存储空间碎片。
链式存储结构
单链表的实现
#include<stdio.h>
#include<stdlib.h>
typedef int elemType;
typedef struct Node
{
elemType data;
struct Node *next;
}Node;
typedef Node *LinkList;
bool initList(LinkList *L)
{
*L=(LinkList)malloc(sizeof(Node));
if(!L) return false;
return true;
}
bool insertElem(LinkList *L,int i,elemType e)
{
int j;
LinkList p,s;
p=*L;
j=1;
while(p && j<i) //寻找第i个结点
{
p=p->next;
j++;
}
if(!p || j>i) return false; //第i个结点不存在
s = (LinkList)malloc(sizeof(Node)); //生成新结点
s->data=e;
s->next=p->next;
p->next = s;
return true;
}
bool deleteElem(LinkList *L,int i) //删除结点
{
LinkList p,q;
int j;
p=*L;
j=1;
while(p->next && j<i)
{
p=p->next;
j++;
}
if(!(p->next) || j>i) return false;
q=p->next;
p->next = q->next;
free(q); //释放结点
return true;
}
elemType getElem(LinkList L,int i) //返回结点
{
int j;
LinkList p;
p=L->next;
j=1;
while(p && j<i)
{
p=p->next;
j++;
}
if(!p || j>i) return -1;
return p->data;
}
int main()
{
LinkList L;
initList(&L);
for(int i=1;i<=10;i++)
insertElem(&L,i,i);
deleteElem(&L,3);
printf("%d\n",getElem(L,3));
}
循环链表
tail->next=head;
双向链表
在单链表的基础上增加了一个前驱的指针域。
至此就先这样了吧。(ps:写博客好难呀。。。)