#define true 1
#define false 0
#define ok 1
#define error 0
#define infeasible -1
#define overflow -2
typedef int status;
//elemtype也可以定义为其它类型
typedef struct{
char name[20];
int age;
}elemtype;
//typedef线性链表类型
typedef struct LNode{
elemtype elem;
struct LNode *next;
}LNode, *Linklist;
// 建一个线性链表的头结点
status Initlist( Linklist &l){
l=(Linklist)malloc(sizeof(LNode));
if(!l){
printf("链表表头失败,无足够空间");
exit(overflow);
}
l->next=NULL;
return ok;
}
status listInsert(Linklist &l,int i,elemtype e){ //在线性链表中第i处插入一个元素e
int j=1; //j=1时,p=head。即j=1时指的是0号位的链表——表头。j=2时指的才是人类语言上1号位的链表。
Linklist p=l;
while(p && j<i){ // 令p为第i-1个结点
p=p->next; // 初始 p=Head j=1 i=3
j++; // 1轮结束 p=1 j=2 i=3
} // 2轮结束 p=2 j=3 i=3 出循环,p恰好为前一个结点
if(!p||j>i){ //当除head所指链表仅有一个有elem的链表时,上面while依然第二轮结束,此时p为NULL,error:i值超过表长+1。
printf("您输入的i值不合法"); //当链表为空,仅有1个head,i=1,即插入1号位,while不执行,p不为NULL,j=i,插入正常进行。
return error; //当链表为空,仅有1个head,i=0,即插入0号位,while不执行,p不为NULL,但j>i,执行if程序。
} //p为i的前驱,!p表明只要p存在,则可以插入。i号位不一定要存在
Linklist s;
Initlist(s);
s->next=p->next;
s->elem=e;
p->next=s;
return ok;
}
status listDelete(Linklist &l,int i,elemtype e) { //删除线性链表的第i处的结点,并将删除的值返回给e
int j=1;
Linklist p=l;
while(p&&j<i){
p=p->next;
j++;
}
if(!p->next||j>i){ //i小于1或者i大于表长。
printf("您输入的i值不合法");
return error;
} //p为i的前驱,!p->next表示必须存在,才能删除。i号位一定要存在。
Linklist q=p->next;
p->next=q->next;
e=p->elem;
free(q);
return ok;
}
status Getlist(Linklist l, int i, elemtype & e){ //取下标i的元素并赋给e
int j=1;
while(l&&j<=i){
l=l->next;
j++;
}
if(!l||i<1){ //注意,这里的i<1不能写成j>i,因为j一定是大于i的
printf("您输入的i值不合法");
return error;
}
e=l->elem;
return ok;
}
status listPrint(Linklist l){ //打印线性链表中所有元素
if(!l) return error;
while(l->next){ //注意:不是l,而是l->next,才能l=l->next,然后打印l。
l=l->next ; //判断条件是l的话,最后一次判断时l->next==NULL,这时无法printf,error。
printf("%s\t%d\n", l->elem.name,l->elem.age);
}
return ok;
}
status Clearlist(Linklist &l){ //重置一个线性链表
Linklist p;
if(!l) return error;
while(l->next ){
p=l->next;
l->next=p->next;
free(p);
}
return ok;
}
status Destroylist(Linklist &l){ //释放一个线性链表
Linklist p;
if(!l) {
return error;
}
while(l ){
p=l;
l=p->next;
free(p);
}
return ok;
}
status listEmpty(Linklist l){ //检查线性链表是否为空。
if(l->next) //空的意思是里面没有有效的元素。如果经摧毁后再判断是否为空则会出错,因为l->next这句执行不了。
return ok;
else
return error;
}
status listLength(Linklist l,int &n){ //测量线性表长度
n=0;
if(!l) return error;
while(l->next){
l=l->next;
n++;
}
return ok;
}
status Sortlist(Linklist &l){ //给线性链表排序。
if(!l) return error;
int is_exchanged=1;
elemtype e;
Linklist t,p;
Initlist(t);
Initlist(p);
while(is_exchanged){
p=l;
is_exchanged=0;
while(p->next->next){
p=p->next;
t=p->next;
if(p->elem.age>t->elem.age){
e=t->elem;
t->elem=p->elem;
p->elem=e;
is_exchanged=1;
}
}
}
return ok;
}
status Reverselist_recursion(Linklist l){ //用递归方法将线性表逆序输出,也可以用栈实现
if(!l) return error;
l=l->next; //一开始想用Reverselist_recursion(l->next)并去掉这句。但是由于链表头的存在,会把链表头的未赋值的elem也打印出来。
if(l->next){ //为了排除表头的特殊情况,只能开始就l->next,不让表头有机会printf。相应的,递归部分的l->next就改成了l。
Reverselist_recursion(l);
}
printf("%s\t%d\n",l->elem.name,l->elem.age);
return ok;
}
status Reverselist_stack(Linklist l){ //将线性链表逆序排列,指针全部反过来
elemtype elems[100];
int top=0;
l=l->next ;
while(l){
elems[top++]=l->elem;
l=l->next;
}
while(top>0){ //如用printf("%s\t%d\n",elems[--top].name,elems[top].age),则会发生错位。原因如下:
printf("%s\t",elems[--top].name); // int sz[5]={0,1,2,3,4};
printf("%d\n",elems[top].age); // int top=3;
} // printf("%d\t%d\n",sz[--top],sz[top]);
} // //2 3
status Reverselist(Linklist &l){ //将线性链表逆序排列。链表原结构逆转。即链表转向
if(!l) return error;
if(l->next&&!l->next->next) return ok; //如果链表中仅有一个元素,正序和逆序一样,直接返回即可
Linklist p1,p2,num1,tmp; //num1为原链表的结点1
num1=p1=l->next;
p2=p1->next;
while(p2){ //若条件为p2,则最后一个结点指向前一结点后,p1=p2;p2=tmp=NULL;tmp=tmp->next=NULL->next,则发生错误。
tmp=p2->next;
p2->next=p1;
p1=p2;
p2=tmp;
}
l->next=p1;
num1->next =p2;
return ok;
}
线性链表
最新推荐文章于 2024-05-16 04:55:22 发布