for(循环)还是while(循环)循环之后,i和条件值相等。





#include<stdio.h>

#include<malloc.h>

#include<stdlib.h>

typedef struct node

{

int data;

struct node *next;

}NODE,*PNODE;

PNODE createList(PNODE );

void travelList(PNODE);

void insertList(PNODE,int,int );

void delList(PNODE,int,int *);

bool isEmpty(PNODE);

int  listLength(PNODE);

void sortList(PNODE);

void main()

{

PNODE phead=(PNODE)malloc(sizeof(NODE));

phead->next=NULL;

//创建单链表

phead=createList(phead);

//遍历单链表

    travelList(phead);

//插入结点至单链表中

printf("开始插入结点,请输入要插入的数据");

int val;

scanf("%d",&val);

insertList(phead,3,val);

//遍历单链表

travelList(phead);

//排序单链表

printf("开始排序\n");

sortList(phead);

//遍历单链表

travelList(phead);

//从单链表中删除结点

printf("开始删除结点");

int val1;

delList(phead,2,&val1);

travelList(phead);

/*//遍历单链表

travelList(phead);

//对单链表中元素进行排序

遍历单链表

travelList(phead);*/


}

PNODE createList(PNODE phead)

{

//创建单链表方法有2种,一种头插法,一种是尾插法。不管什么方法都需要创造新的节点都要挂到头结点上。

//你要造出一个结点,就得给结点赋值,创造一个赋值,2个赋值,多了,肯定要循环。你直接指定节点个数不就好了吗

/*尾插法思想

PNODE ptail=phead;

printf("请输入当前结点个数\n");

int len;

scanf("%d",&len);

for(int i=0;i<len;i++)

{

PNODE pnew=(PNODE)malloc(sizeof(NODE)*len);

if(NULL==pnew)

{

printf("内存分配失败");

exit(-1);

}

else

{

printf("请给当前第%d个结点赋值",i+1);

int temp;

scanf("%d",&temp);

pnew->data=temp;

pnew->next=NULL;

}

phead->next=pnew;

phead=pnew;

}

return ptail;*/

//头插法思想

printf("请输入当前结点个数\n");

int len;

scanf("%d",&len);

for(int i=0;i<len;i++)

{

PNODE pnew=(PNODE)malloc(sizeof(NODE)*len);

if(NULL==pnew)

{

printf("内存分配失败");

exit(-1);

}

else

{

printf("请给当前第%d个结点赋值",i+1);

int temp;

scanf("%d",&temp);

pnew->data=temp;

pnew->next=NULL;

pnew->next=phead->next;

phead->next=pnew;

}


}

return phead;

}

void travelList(PNODE phead)

{

PNODE p=phead->next;

while(p!=NULL)

{

printf("%d ",p->data);

p=p->next;

}

printf("\n");

}

void insertList(PNODE phead,int pos,int val)

{

//最初的算法,可以实现,但是效率不高!

/*if(pos<1||pos>listLength(phead)+1)

{

printf("插入不合法,请重新插入");

return ;

}

PNODE pnew=(PNODE)malloc(sizeof(NODE));

pnew->data=val;

pnew->next=NULL;

//想插入结点,先找到其前面的一个结点。其实插入结点的时候,就是要将已经建立好的链表给弄断了,弄断了之后能不能接上问题。

// 只有找到前面的结点,能够接上,如果你找后面,接不上,或者效率很低。

int i=0;

PNODE ptemp=phead;

while(i<pos-1)

{

ptemp=ptemp->next;

i++;

}

pnew->next=ptemp->next;

ptemp->next=pnew;*/

// 高效率算法来了,不用来计算链表长度.

//按位置找,按位置插入,就不用判断链表的长度了。这种算法效率高些!

PNODE pnew=phead;

/*

这个方法只适用于不用循环的链表。

*/

PNODE p=phead;

int i=0;

//我不管你链表长度是多少,其实考虑问题无非有3:第一你这个链表存不存在(注意不是有没有结点问题),第二,你插入位置合不合法,负数怎么办

//第三,你插入的位置,我链表的长度,够不够,我没有那么长,你非要在很大很大的长度上插入。

//方法是这样解决的:我不管,顺着找,先找到要插入位置的前面的那个结点。

while(NULL!=p&&i<pos-1)//去掉了链表存不存在的问题(注意光NULL!=p&&i<pos-1,解决不了循环链表的问题,结点p始终不等于NULL)

{

p=p->next;

i++;

}

if(i>pos-1||NULL==p) //判断前方的那个结点是否存在,去掉了长度问题,去掉了链表合不合法的问题。

{

return;

}

//开始插入结点

PNODE pnew=(PNODE)malloc(sizeof(NODE));

pnew->next=NULL;

pnew->data=val;


pnew->next=p->next;

p->next=pnew;

}

int  listLength(PNODE phead)

{

int i=0;

PNODE pnew=phead->next;

while(pnew!=NULL)

{

i++;

pnew=pnew->next;

}

return i;

}

bool isEmpty(PNODE phead)

{

if(phead->next==NULL)

return true;

else

return false;

}

void sortList(PNODE phead)

{

int temp;

int i,j;

PNODE pnew;

for(i=0;i<listLength(phead)-1;i++)

for(j=0,pnew=phead->next;j<listLength(phead)-1-i;j++,pnew=pnew->next)

{

if(pnew->data>pnew->next->data)

{

//交换数据。

temp=pnew->next->data;

pnew->next->data=pnew->data;

pnew->data=temp;

}

}

}

void delList(PNODE phead,int pos,int *val)

{

int i=0;

PNODE pnew=phead;

if(pos<1&&pnew==NULL)//这个地方都不用判断为空,效率高吧!

{

printf("对不起,无法删除");

return;

}

for(i=0;i<pos-1&&pnew!=NULL;i++)

{

pnew=pnew->next;

}

PNODE q=pnew->next;

*val=pnew->next->data;

pnew->next=pnew->next->next;

printf("%d\n",*val);

free(q);


}