时间:2017年1月25日,21:17:16
自学于郝斌老师
创建链表
PONDE Create_list(void)
{
PONDE pHead = (PONDE)malloc(sizeof(NODE));//创建头节点
PONDE pTail = pHead;//创建尾节点,尾节点等于头节点
pTail->pNext = NULL;//一定要把尾节点的指针域清空,适用于零个节点的情况
int len;//len为链表的节点个数
scanf("%d", &len);
int val//val为临时保存节点数据域的变量
for(int i=1;i<=len;i++)
{
scanf("%d", &val);
PONDE pNew = (PONDE)malloc(sizeof(NODE));//创建一个节点,保存新数据
pNew->data = val;//新节点保存临时数据
pTail->pNext = pNew;//尾节点指向新节点,第一次循环时也就等于头节点指向下一个节点
pNew->pNext = NULL;//把新节点的指针域清空
pTail = pNew;//尾节点等于新节点,pTail时刻指向尾节点
}
return pHead;
}
//为什么创建链表的函数是PONDE 类型
// 因为在主函数中的头指针是PONDE类型,创建完链表需要返回pHead。
//此时,它们俩唯一的要求,就是类型相同才可以接受返回值!
遍历链表
void Traverse_list(PNODE pHead)
{
PNODE ;//一定要记住什么时候也不要改变头节点的位置。所以用临时一个P代替头节点进行操作
while (p != NULL)//p = pHead->pNext :p等于头节点之后的第一个节点。
{ //假设5个节点,循环到第5个节点之后,p = pHead->pNext,这时尾节点的指针域是空的,NULL,循环结束
printf("%d ", p->data);
p = p->pNext;//往下循环
}
printf("\n");
return;
}
链表的排序
void Sort_list(PONDE pHead)
{
PONDE p, q;//这个排序很好诠释了泛型算法。
int i, j, temp;
int len = length_list(pHead);
for (p = pHead->pNext, i = 0;i < len - 1;i++,p=p->pNext)
{
for (q = p->pNext,j = i + 1;j < len;j++, q = q->pNext)
{
if (p->data < q->data)
{
p->data = temp;
p->data = q->data;
q->data = temp;
}
链表的删除节点
bool Delete_list(PONDE pHead, int pos, int *pVal)
{
int i = 0;
PONDE p = pHead;//循环结束的节点位置在删除节点位置的前一个
//与增加节点不同的是:删除的节点位置不可能是尾节点之后的节点
//p->pNext = p->pNext->pNext;第4个节点的指针域等于第5个节点的指针域,也就等于尾指针的指针域,为空
while (p->pNext != NULL&&i < pos - 1)
{
p = p->pNext;
i++;
}
if (i > pos - 1 || p->pNext == NULL)
return false;
PONDE q = p->pNext;
*pVal = q->data;
p->pNext = p->pNext->pNext;
free(q);//这两步操作是删除节点的必要操作
q=NULL:
return true;
}
//假设有5个节点:1.我要删除第5个节点,必须在第4个节点循环停止,所以循环条件是:p->pNext != NULL
// 2.我要增加第6个节点,我可以一直循环到第5个节点后,所以循环条件是:p != NULL
链表的增加节点
bool Insert_list(PONDE pHead, int pos, int val)
{
int i = 0;
PONDE p = pHead;//一定要记住:p = pHead
while (p != NULL&&i < pos - 1)//p!=NULL,如果有5个节点,增加节点位置是6
//刚刚到循环完第5个节点后结束,因为尾节点的指针域为空
{ //要记住:应该循环到增加节点位置的前一个节点结束,我要在第四个节点位置增加节点,应该在第三个节点结束
i++;
p = p->pNext;
}
if (p == NULL || i > pos - 1)
return false;
PONDE pNew = (PONDE)malloc(sizeof(NODE));
pNew->data = val;
//第一种增加节点的方式
PONDE q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;
//第二种增加节点的方式
pNew->pNext = p->pNext;
p->pNext = pNew;
}
判断是否空链表
bool Empty_list(PNODE pHead)
{
if (pHead->pNext == NULL)//如果头节点的指针域为空,意思就是头节点根本没有其他节点的地址,此时链表就为空
return true;
else
return false;
}
求出链表长度
int Length_list(PONDE pHead)
{
PONDE p = pHead->pNext;//这个没什么好说的
int len = 0;
while (p != NULL)
{
p = p->pNext;
len++;
}
return len;
}
代码如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;//数据域
struct Node *pNext;//指针域
}NODE,*PNODE;//NODE等价于struct NODE PNODE等价于struct Node *
PNODE create_list(void);
void traverse_list(PNODE pHead);
bool is_empty(PNODE);
int length_list(PNODE pHead);
bool insert_list(PNODE,int,int);
bool delete_list(PNODE,int,int *);
PNODE sort_list(PNODE);
int main(void)
{
PNODE pHead = NULL;//等价于 struct Node * pHead = NULL;
pHead = create_list();//create_list()功能:创建一个非循环单链表,并将该链表的头结点的地址赋给pHead
printf("遍历链表输出为:\n");
traverse_list(pHead);
int len=length_list(pHead);
printf("链表的长度是%d",len);
int flag=1;
if( is_empty(pHead))
{
printf(",并且链表为空。\n");
flag=0;
}
else
{
printf(",并且链表不为空.\n");
}
if(flag)
{
printf("升序后的链表为:\n");
sort_list(pHead);
traverse_list(pHead);
int pos1,val1;
printf("请输入您要插入节点的位置:\n");
scanf("%d",&pos1);
printf("请输入您要插入节点的值:\n");
scanf("%d",&val1);
if(insert_list(pHead,pos1,val1))
{
printf("插入成功,您插入的元素是:%d\n",val1);
printf("插入此节点后的链表为:\n");
traverse_list(pHead);
}
else
{
printf("插入失败!您插入的位置不存在!\n");
}
int pos2,val2;
printf("请输入您要删除节点的位置:\n");
scanf("%d",&pos2);
if(delete_list(pHead,pos2,&val2))
{
printf("删除成功,您删除的元素是:%d\n",val2);
printf("删除此节点后的链表为:\n");
traverse_list(pHead);
}
else
{
printf("删除失败!您删除的元素不存在!\n");
}
}
return 0;
}
PNODE create_list(void)
{
int len;//用来存放有效节点的个数
int i;
int val;//用来临时存放用户输入的结点的值
PNODE pHead =(PNODE)malloc(sizeof(NODE));//分配了一个不存放有效数据的头结点
if(pHead==NULL)
{
printf("分配失败,程序终止!\n");
exit(-1);
}
PNODE pTail=pHead;
pTail->pNext=NULL;
printf("请输入您需要生成的链表节点的个数:");
scanf("%d",&len);
for(i=0;i<len;i++)
{
printf("请输入第%d个节点的值:",i+1);
scanf("%d",&val);
PNODE pNew =(PNODE)malloc(sizeof(NODE));//每次循环都分配一个节点。
if(pNew==NULL)
{
printf("分配失败,程序终止!\n");
exit(-1);
}
pNew->data = val;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;//指针pTail 时刻指向尾指针域
}
return pHead;
}
void traverse_list(PNODE pHead)
{
PNODE p=pHead->pNext;
while(p!=NULL)
{
printf("%d ",p->data);
p=p->pNext;
}
printf("\n");
return;
}
bool is_empty(PNODE pHead)
{
if(pHead->pNext==NULL)
return true;
else
return false;
}
int length_list(PNODE pHead)
{
PNODE p=pHead->pNext;
int len=0;
while(p!=NULL)
{
len++;
p=p->pNext;
}
return len;
}
PNODE sort_list(PNODE pHead)
{
int i,j,t;
PNODE p,q;
int len=length_list(pHead);
for(i=0,p=pHead->pNext;i<len-1;i++,p=p->pNext)
{
for(j=i+1,q=p->pNext;j<len;j++,q=q->pNext)
{
if(p->data>q->data)
{
t=p->data;
p->data=q->data;
q->data=t;
}
}
}
//return;
}
//在pHead 所指向链表的第pos个节点的前面插入一个新的结点,该节点的值是val,并且pos是从1开始
bool insert_list(PNODE pHead,int pos,int val)
{
int i=0;
PNODE p=pHead;
while(p!=NULL&&i<pos-1)
{
p=p->pNext;
i++;
}
if(i>pos-1||p==NULL)
return false;
PNODE pNew=(PNODE)malloc(sizeof(NODE));
if(pNew==NULL)
{
printf("动态分配内存失败\n");
exit(-1);
}
pNew->data=val;
PNODE q=p->pNext;
p->pNext=pNew;
pNew->pNext=q;
return true;
}
bool delete_list(PNODE pHead,int pos,int *pVal)
{
int i=0;
PNODE p=pHead;
while(p->pNext!=NULL&&i<pos-1)
{
p=p->pNext;
i++;
}
if(i>pos-1||p->pNext==NULL)
return false;
PNODE q=p->pNext;
*pVal=q->data;
p->pNext=p->pNext->pNext;
free(q);
q=NULL;
return true;
}