最近新学的关于链表的操作,做了一个小小的总结吧,链表的一些简单操作。
文笔比较拙略,望高手谅解,指正。
代码均已经在dev上测试运行,保证无错。
如果有和我一样的新手大家可以一起交流一下。
#include <stdio.h>
#include <stdlib.h>
struct test
{
int a;
struct test *next;
};
struct test *Creat_from_head();
struct test *Creat_from_tail();
void print(struct test *head);
struct test *antitone1(struct test *head);
struct test *antitone2(struct test *head);
struct test *sort1(struct test *head);
struct test *sort2(struct test *head);
int main(void)
{
int item;
struct test *p1;
struct test *p2;
struct test *p3;
printf("创建链表(以0结束),请选择创建的方式\n");
printf("1 头插法\n");
printf("2 尾插法\n");
scanf("%d",&item);
fflush(stdin);
printf("\n");
switch(item)
{
case 1:
{
p1=Creat_from_head();
break;
}
case 2:
{
p1=Creat_from_tail();
break;
}
default :
{
break;
}
}
printf("\n");
print(p1);
printf("\n");
printf("选择链表的反序方式\n");
printf("1 三变量反序\n");
printf("2 两变量反序\n");
scanf("%d",&item);
fflush(stdin);
printf("\n");
switch(item)
{
case 1:
{
p2=antitone1(p1);
break;
}
case 2:
{
p2=antitone2(p1);
break;
}
default :
{
break;
}
}
print(p2);
printf("\n");
printf("\n");
printf("选择链表的排序方式\n");
printf("1 直接排序\n");
printf("2 选择排序\n");
scanf("%d",&item);
fflush(stdin);
printf("\n");
switch(item)
{
case 1:
{
p3=sort1(p2);
break;
}
case 2:
{
p3=sort2(p2);
break;
}
default :
{
break;
}
}
print(p3);
printf("\n");
return 0;
}
struct test *Creat_from_tail()
{
struct test *head;
struct test *pnew;
struct test *tail;
pnew=(struct test *)malloc(sizeof(struct test));
pnew->next=NULL;
head=pnew;
tail=pnew;
while(1)
{
pnew=(struct test *)malloc(sizeof(struct test));
scanf("%d",&pnew->a);
if(pnew->a==0)
{
free(pnew);
return head;
}
pnew->next=NULL;
tail->next=pnew;
tail=pnew;
}
}
/*头插法创建链表*/
struct test *Creat_from_head()
{
struct test *head;
struct test *pnew;
head=(struct test *)malloc(sizeof(struct test));
head->next=NULL;
while(1)
{
pnew=(struct test *)malloc(sizeof(struct test));
scanf("%d",&pnew->a);
if(pnew->a==0)
{
free(pnew);
return head;
}
pnew->next=head->next;
head->next=pnew;
}
}
/*用于输出链表 */
void print(struct test *head)
{
struct test *p;
p=head->next;
while(p!=NULL)
{
printf("%d\n",p->a);
p=p->next;
}
}
/*链表的直接比较排序(名字可能不太恰当) (由小到大)*/
struct test *sort1(struct test *head)
{
struct test *p; /*这是无序链表的遍历结点*/
struct test *q1,*q2; /*q1,q2都是有序链表中的结点,q2用来和无序链表中的结点比较,q1用来保存q1前面的结点,从而方便新结点的插入*/
struct test *tem; /*用来保存当前无序链表中的结点,若是不保存这个结点,在每次将无序链表中结点插入,有序链表后,无序链表将无法遍历,程序陷入崩溃*/
p=head->next->next; /*这里两句是将一个链表一刀截断,分成两个,一个是存储有序的,另一个是存储无序*/
head->next->next=NULL;
while(p!=NULL) /*当p等于NULL时候无序连表遍历完毕,也意味着排序完毕*/
{
tem=p; /* 无序链表部分 */
p=p->next;
q1=head;
q2=head->next; /*有序链表部分*/
while(q2!=NULL)
{
if(q2->a<tem->a)
/*这里是排序的重点,每次从无序链表中取出的结点都要和有序链表的第
一个有值结点比较(因为咱们创建的链表是有表头的),比这个结点大则继续向下遍历无序链表,如果小则结束遍历,直接将这个
结点插入到有序链表中的第一个有值位置之前*/
{
q1=q2;
q2=q1->next;
}
else
{
break;
}
}
q1->next=tem; /*将无序链表中找出的结点插入到有序链表中*/
tem->next=q2;
}
return head;
}
/*用来反序链表 (把删除放到这里,是应为这个思想和上面排序的思想有一定的相似)*/
struct test *antitone1(struct test *head)
{
struct test *p1,*p2; /*p1,是遍历用的,p2,永远都是前面链表的第一个有值结点(被插入链表的第一个有值结点)*/
struct test *q; /*保存p1的后面结点,因在结点的插入过程p1后面的结点会丢掉,导致无法遍历后面的结点(原因同sort1()中的q1,q2)*/
p1=head->next->next;
p2=head->next;
head->next->next=NULL;
while(p1!=NULL)
{
q=p1->next; /*保存p1后面的结点*/
head->next=p1; /*这里是插入过程也是这个功能的重点*/
p1->next=p2;
p2=p1; /*这样p2又成了第一个有值结点*/
p1=q; /*用于移动*/
}
return head;
}
/*想比上面那这种,这种我觉得更加简洁明了,而且自己定义两个变量就完成了逆置*/
struct test *antitone2(struct test *head)
{
struct test *p=head->next,*q=head->next;/*p为当前插入前面链表的结点,q保存p的下一个节点(原因和上面antitone1()中q类似)*/
q=q->next;
p->next=NULL;
p=q;
while(p!=NULL)
{
q=q->next;
p->next=head->next; /*这里与上面的反序不同,它不管你head下面的是谁,只管向head下面添加就够了,剩下了变量,也更明了*/
head->next=p;
p=q;
}
return head;
}
/*链表的选择排序 (由小到大)*/
/*这个方法是在原始链表中找到最小结点后,放入新链表,并且把找到的最小在原先链表中删除*/
struct test *sort2(struct test *head)
{
struct test *sorted,*tail; /*sorted有顺序的链表的两个结点*/
struct test *min,*p_min; /*保存最小结点,和最小结点的前一个结点(方便删除)*/
struct test *p; /*临时结点*/
sorted=(struct test *)malloc(sizeof(struct test)); /*为新链表创建表头*/
sorted->next=NULL;
while(head->next!=NULL)
{
for(p=head->next,min=head->next,p_min=head;p->next!=NULL;p=p->next) /*此处找出最小的结点*/
{
if(p->next->a<min->a)
{
min=p->next;
p_min=p;
}
}
if(sorted->next==NULL) /*将找出的插入到有序链表中*/
{
sorted->next=min;
tail=min;
}
else
{
tail->next=min;
tail=min;
}
p_min->next=min->next; /*将最小的结点在原链表删除*/
}
if(sorted->next!=NULL)
{
tail->next=NULL;
}
head=sorted;
return head;
}