最近在看数据结构,来写点笔记~~~
先看基本定义
线性表:由同类型数据元素构成有序序列的线性结,是最基本、最简单、也是最常用的一种数据结构。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。其中;
表中元素个数称为线性表的长度,
当线性表没有元素时,称为空表,表的起始位置称为表头,表的结束位置称为表尾。
我们再来看一些基本操作的实现:
先定义一个结构体
typedef struct{
Element Type Data[MAXSIZE];
int Last;
}List;
List L,*PtrL;
定义这个结构体可以实现简单的操作:
L.Data[i]或PtrL->Data[i] //访问下标为i的元素
L.Last+1或PtrL->Last+1 //可以表示线性表的长度
//1.初始化线性表
List *MakeEmpty(){
List *PtrL;
PtrL = (List *)malloc( sizeof(List) );//向系统请求List长度个内存空间
PtrL -> Last = -1;//下标为0就是有一个元素了,所以-1就代表没有元素,即数组为空。
return PtrL;
}
2.查找操作
//查找X
int Find(ElementType, List *PtrL){
int i=0;//准备开始
while(i<=PtrL->Last &&PtrL->Data[i]!=X)//如果i在线性表范围内并且不等于X时,则+1
i++;
if (i >PtrL->Last ) return -1; //i一直加当它超出范围时,返回-1
else return i;//找到则返回i。
}
3.插入操作:把握一个关键就是插入的时候需要把某点以后的所有元素依次后移。
void Insert (ElementType X, int i, List *PtrL){
int j;
if( PtrL->Last==MAXSIZE-1){ //如果表满了的话则不能插入
printf( "表满 " );
return;
}
if( i<1 || i > PtrL->Last+2){ //判断位置。
printf(" 位置不合法 ");
return;
}
for( j=PtrL->Last; j>=i-1; j--)
PtrL->Data[ j+1 ] = PtrL->Data[j];//前一位向后移动
PtrL->Data[i-1]=X; //插入新元素
PtrL->Last++; //Last指向最后一个元素
return;
}
4.删除操作
void Delete( int i ,List *PtrL){
int j;
if( i <1 || i>PtrL->Last+1){ //查无此数的条件
printf("不存在第%d个元素");
return ;
}
for ( j = 1; j <= PtrL -> Last; j++ )
PtrL ->Data[j-1] =PtrL -> Data[j]; //直接将后面的数向前移,要删除的数就被覆盖了
PtrL->Last--; //因为少了一个数 Last要减一
return;
}
如我们所见线性表的插入、删除操作需要移动大量元素,效率低而且表的长度难以确定,接下来我们看另一种存储结构——链式存储。
链式存储不要求逻辑上相邻的两个元素物理上也相邻;插入、删除不需要移动数据元素,只需要修改“链”。也就是说,表中的数据不需要一个挨着一个排列,这就没有上面顺序存储结构中删除和插入时将所有数据移动的问题,这样会更有效率~~~
我们来看看基本操作~
先定义结构体
typedef struct Node{
ElementType Data;
struct Node *Next;
}List;
List L, *PtrL;
1.求表长
int Length ( List *PtrL){
List *p = PtrL; //p指针指向表中第一个结点
int j=0;
while ( p ){
p = p->Next; //当p不为空时,指向下一个结点然后j++,从而算出表长
j++;
}
return j;
}
2.链表查找
(1)按序号查找
List *FindKth( int K, List *PtrL){
List *p = PtrL; // //p指针指向表中第一个结点
int i = 1;
while ( p != NULL && i<K ){ //判断是否在合法范围内
p=p->Next;
i++;
}
if ( i == K) return p; //找到了第K个元素,返回指针;
else return NULL; //查找失败,返回空。
}
(2) 按值查找
List *Find ( ElementType X,List *PtrL){
List *p = PtrL;
while ( p != NULL && p->Data != X )
p = p->Next;
return p;
}
3.插入操作
List *Insert ( ElementType X, int i, List *PtrL ){
List *p, *s;
if( i == 1){ //插入表头
s = (List *)malloc(sizeof(List)); //分配存储单元
s->Data = X;
s->Next = PtrL;
return s;
}
p = FindKth( i-1, PtrL); //查找第i-1个结点
if( p == NULL){ //结点不存在
printf( "参数i错误! " );
return NULL;
}else{ //结点存在,分配存储单元后直接插入i-1个结点的后面
s=(List *)malloc(sizeof(List));
s->Data = X;
s->Next = p->Next;
p->Next = s;
return PtrL;
}
}
总结一下原理~~
1.先构造一个新结点,用s指向;
2.再找到链表的第i-1个结点,用p指向;
3.修改指针,插入结点。
其中值得注意的是
s->Next = p->Next; p->Next = s;
这两步不能交换,如果先进行了后者,则p的后一个结点则不存在~~~
4.删除操作
List *Delete( int i,List *PtrL){
List *p, *s;
if( i == 1){ //删除第一个结点
s=PtrL; //s指向第一个结点
if( PtrL != NULL) PtrL = PtrL -> Next; //直接覆盖掉~~
else return NULL;
free( s ); //释放内存
return PtrL;
}
p = FindKth( i-1,PtrL ); //查找第i-1个结点
if( p == NULL){ //不存在的情况
printf("第%d个结点不存在 ",i-1); return NULL;
}else if (p->Next == NULL){
printf("第%d个结点不存在",i); return NULL;
}else{
s = p->Next; //s指向第i个结点
p->Next = s->Next; //删除~!~
free(s);
return PtrL;
}
}
总结一下链表的删除操作~~
1.先找到链表的第i-1个结点,用p指向;
2.再用指针s指向要被删除的结点 p->Next;
- 修改指针,删除s所指结点
4.释放s所指结点的空间~
that's all~~~
点击查看更多内容
66人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦