自己理解,方便自己21考研使用
目前在通过西北大学的耿国华老师的上课课程实录视频在学习数据结构。在链表的提高课程上给出了三个习题,分别为:
1.分解链表奇和偶两部分,前半部分为奇数,后半部分为偶数,算法复杂度要求为O(1)。
2.单链表就地逆置
3.二进制数加1运算
本篇先介绍第一个问题:
(一)前提知识
首先是顺序表的定义,应该为:
#define MAXSIZE 100
typedef struct //定义了数组类型结构,实现顺序存储
{
int elem[MAXSIZE];
int last; //就是数组的最大下标
}SeqList;
SeqList L; //实例化一个结构体
定义了一个结构体,在对顺序表的操作,也仅仅是对这一个结构体中的数组进行操作,不同于单链表有多个结构体,每个结构体串联形成一个表。
注意:下面语句:
SeqList *p=&L;
意思是定义一个上面定义的结构体类型的指针,全程代码视线中,也仅仅就此一个指针,这个指针指到上面的结构体,通过这个指针就可做到访问数组elem[]与last的值的操作。通过下面语句访问:
p->elem[i]; //访问数组elem[]中,下标为i的值
p->last; //访问last
(二)实现算法
本题目需要实现奇数与偶数分两边存储,其实现代码如下:
AdjustSqlist(SeqList *L)/*利用顺序表调整其为左右两部分,左边的为奇数,右边的为偶数*/
{
int i=0,j=L->last;
int t;
while(i<j)
{
while(L->elem[i]%2!=0)
i++;
while(L->elem[j]%2==0)
j--;
if(i<j)
{
t=L->elem[i];
L->elem[i]=L->elem[j];
L->elem[j]=t;
}
}
}
代码解释:
由于题目要求复杂度为O(1),故也就是说复杂度就是访问一遍就能得出结果,故选择以此算法来实现。
代码中定义了变量i 与变量j,其初始为这个数组的第一个元素的下标与最后一个元素的下标。
左边的变量i用于寻找偶数,找到偶数,停下来;见了奇数就往后移动一位;这样变量i,前面的就能保证全是奇数。
右边的变量j用于寻找奇数,找到奇数,停下来;见了偶数就往前移动一位:这样变量j,后面的就能保证全是偶数。
使用while循环,当i找到第一个偶数,j找到第一个奇数时,停下来时,对这两个数进行交换。
交换过后,继续寻找,找到继续交换
什么时候停下来呢?
在i>j的时候,因为此时,说明i与j已经相交,也就说明实现了对全数组的遍历和操作。那实现了这些,数组真的就是左边奇数,有边偶数吗?
是的,因为变量i,前面的就能保证全是奇数。变量j,后面的就能保证全是偶数。
一重合就表明已经实现了要求。
(三)完整代码
/*利用顺序表调整其为左右两部分,左边的为奇数,右边的为偶数*/
#define MAXSIZE 100
typedef struct //定义了数组类型结构,实现顺序存储
{
int elem[MAXSIZE];
int last; //就是数组的最大下标
}SeqList;
AdjustSqlist(SeqList *L)/*利用顺序表调整其为左右两部分,左边的为奇数,右边的为偶数*/
{
int i=0,j=L->last;
int t;
while(i<j)
{
while(L->elem[i]%2!=0)
i++;
while(L->elem[j]%2==0)
j--;
if(i<j)
{
t=L->elem[i];
L->elem[i]=L->elem[j];
L->elem[j]=t;
}
}
}
void main()//主函数
{
SeqList l;
int p,q,r,i,j;
printf("请输入线性表的长度:");
scanf("%d",&p);
l.last=p-1;
printf("/n请输入线性表中各元素的值:");
for(i=0;i<=l.last;i++)
scanf("%d",&l.elem[i]);
AdjustSqlist(&l);//参数为指向结构体l的指针
printf("/n调整后的顺序表为");
for(i=0;i<=l.last;i++)
//scanf("%d",&l.elem[i]);
printf("%d ",l.elem[i]);
}