/*
* 根据郝斌老师视频整理
* 编译环境:
* guo@linux:~$ gcc --version
* gcc (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
*/
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#define FALSE 0
#define TRUE 1
typedef struct Node
{
int data; /*数据域*/
struct Node *pNext; /*指针域*/
}NODE, *PNODE;
/**********************声明**********************************/
/*创建链表*/
PNODE CreateLink(void);
/*遍历链表*/
void TraverseLink(PNODE );
/*判断链表是否为空*/
int IsEmptyLink(PNODE );
/*求链表长度*/
int LengthLink(PNODE );
/*链表排序*/
void SortLink(PNODE );
/*链表插入节点*/
int InsertLink(PNODE , int , int );
/*链表删除节点*/
int DeleteLink(PNODE , int , int *);
/*
* 函数名称:CreateLink。
* 输入参数:无。
* 输出参数:返回头节点的指针。
* 函数说明:创建一个链表,并由用户输入每个节点的值。
*/
PNODE CreateLink(void)
{
int len; /*链表个数*/
int val; /*存储临时值*/
int i;
/*为头节点分配内存,并把地址赋值给pHead*/
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if (NULL == pHead)
{
printf("内存分配失败!\n");
exit(-1);
}
PNODE pTail = pHead;
pTail->pNext = NULL;
printf("请输入链表的个数:len=\n");
scanf("%d",&len);
for (i=0;i<len;++i)
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("内存分配失败!\n");
exit(-1);
}
printf("请输入第%d个节点的值:\n",i+1);
scanf("%d",&val);
pNew->data = val; /*保存新节点的数据*/
pNew->pNext = NULL; /*新节点的指针指向NULL*/
pTail->pNext = pNew; /*上个节点的指针指向新节点*/
pTail = pNew; /*pTail指向新节点(保存新节点地址)*/
}
return pHead;
}
/*
* 函数名称:TraverseLink。
* 输入参数:pHead链表头节点的指针。
* 输出参数:无。
* 函数说明:遍历一个链表,并输出每个节点的值。
*/
void TraverseLink(PNODE pHead)
{
PNODE p = pHead->pNext; //p指向第一个有效节点(首节点)
while(NULL != p)
{
printf("%d ", p->data);
p = p->pNext;
}
printf("\n");
return;
}
/*
* 函数名称:IsEmptyLink。
* 输入参数:pHead链表头节点的指针。
* 输出参数:为空返回TRUE;否则返回FALSE。
* 函数说明:判断一个链表是否为空。
*/
int IsEmptyLink(PNODE pHead)
{
if (NULL == pHead->pNext)
return TRUE;
else
return FALSE;
}
/*
* 函数名称:LengthLink。
* 输入参数:pHead链表头节点的指针。
* 输出参数:链表长度。
* 函数说明:求链表长度。
*/
int LengthLink(PNODE pHead)
{
int len = 0;
PNODE p = pHead->pNext;
while (NULL != p)
{
++len;
p = p->pNext;
}
return len;
}
/*
* 函数名称:SortLink。
* 输入参数:pHead链表头节点的指针。
* 输出参数:无。
* 函数说明:选择排序,升序。
*/
void SortLink(PNODE pHead)
{
int i,j,t,len;
PNODE p,q;
len = LengthLink(pHead);
/*i,j决定循环次数*/
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;
}
/*
* 函数名称:InsertLink。
* 输入参数:pHead链表头节点的指针;pos要插入的位置,从1开始;value要插入的值;
* pos可以比链表长度大1。
* 输出参数:插入成功返回TRUE,否则返回FALSE。
* 函数说明:插入一个节点。
* 假设有5个节点,如下所示:
* pHead 节点1 节点2 节点3 节点4 节点5
* OOOO——>OOOO——>OOOO——>OOOO——>OOOO——>OOOO
* 假设pos=3,即在第三个节点前插入数值。在while语句中带入数值:
* 1)初始值: i=0,p指向pHead
* 2)while成立:i=1,p指向节点1
* 3)while成立:i=2,p指向节点2
* 4)2<3-1不成立,所以此时可以确定pos没有超过链表长度,p正好指向第三个节点的
* 前一个节点。
* 5)如果只有2个节点,pos=3的话,在经过3)后,p指向节点2,此时p!= NULL,
* p->pNext = NULL。此时while语句的前半部分成立,后半部分不成立,所以while的
* 判断条件适合pos的值可以比链表的长度大1.
*/
int InsertLink(PNODE pHead, int pos, int value)
{
int i = 0;
PNODE p = pHead;
/*利用循环找到pos位置,或者到尾节点*/
while (NULL!=p && i<pos-1)
{
p = p->pNext;
++i;
}
/*从while循环中可以得知,i>pos-1不会成立,在此加一个是为了保证逻辑严密??*/
/*如果因为NULL==p导致while退出循环,说明pos超过链表的长度*/
if (i>pos-1 || NULL==p)
return FALSE;
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("动态分配内存失败!\n");
exit(-1);
}
pNew->data = value;
pNew->pNext = p->pNext;
p->pNext = pNew;
return TRUE;
}
/*
* 函数名称:DeleteLink。
* 输入参数:pHead链表头节点的指针;pos要删除的位置,从1开始;value保存要删除节点的值。
* 输出参数:删除成功返回TRUE,否则返回FALSE。
* 函数说明:删除一个节点。思路跟InsertLink相同,注意要释放内存。
*/
int DeleteLink(PNODE pHead, int pos, int *pValue)
{
int i = 0;
PNODE p = pHead;
while (NULL!=p && i<pos-1)
{
p = p->pNext;
++i;
}
if (i>pos-1 || NULL == p)
return FALSE;
/*此时p指向pos的前一个节点*/
*pValue = p->pNext->data;
PNODE q = p->pNext;
p->pNext = p->pNext->pNext;
free(q);
q = NULL;
return TRUE;
}
int main(void)
{
PNODE pHead = NULL;
int DeleteVal; /*存储删除的值*/
pHead = CreateLink();
TraverseLink(pHead);
if (IsEmptyLink(pHead))
printf("链表为空!\n");
else
printf("链表非空!\n");
printf("链表长度为%d\n",LengthLink(pHead));
printf("链表按升序排列为:\n");
SortLink(pHead);
TraverseLink(pHead);
printf("链表插入一个值:\n");
InsertLink(pHead, 3, 33);
TraverseLink(pHead);
printf("链表删除一个值:\n");
DeleteLink(pHead, 2, &DeleteVal);
TraverseLink(pHead);
printf("链表删除的值为%d:\n",DeleteVal);
return 0;
}
|