数据结构--非循环单链表

include<stdio.h>

include<stdlib.h>//exit 的头文件,exit功能是终止该程序

include<malloc.h>

typedef struct Node
{
int data; //数据域
struct Node * pNext; //指针域
} NODE, *PNODE;

/*
typedef的功能是给数据类型重新再造一个名词来使用
上面结构体中,struct Node 等价于 NODE
struct Node * 等价于 PNODE
*/

//函数声明
PNODE create_list(); //创建非循环单链表
void traverse_list(PNODE pHead); // 链表输出
bool is_empty(PNODE pHead); //判断链表是否为空
int length_list(PNODE pHead); //求链表长度
void sort_list(PNODE pHead); //对链表进行排序
bool insert_list(PNODE pHead, int pos, int val);
//在pHead所指向链表的第pos个节点的前面插入一个新的结点,该节点的值是val,
//并且pos的值是从1开始
bool delete_list(PNODE pHead, int pos, int * pVal);
//删除链表第pos个节点,并将删除的结点的值存入pVal所指向的变量中, 并且pos的值是从1开始

int main(void)
{
int val;

PNODE pHead = NULL;      //创建链表头节点

pHead = create_list();  //创建非循环单链表
traverse_list(pHead);   // 链表输出

if(is_empty(pHead))
	printf("链表为空!\n");
else
	printf("链表不为空!\n");


int len = length_list(pHead);  //求链表长度
printf("链表的长度为:%d\n",len);

sort_list(pHead);//对链表进行排序,从小到大
traverse_list(pHead); // 链表输出


insert_list(pHead, 4, 88);//对链表进行插入新节点
traverse_list(pHead); // 链表输出


if(delete_list(pHead, 5, &val))
{
	printf("删除成功,你删除的元素是%d\n",val);
}
else
{
	printf("删除失败!你删除的元素不存在!\n");
}

traverse_list(pHead); // 链表输出


return 0;

}

//删除第pos个节点,并将删除的结点的值存入pVal所指向的变量中
bool delete_list(PNODE pHead, int pos, int * pVal)
{

int i = 0;

PNODE p = pHead;

while(NULL!=p->pNext && i<pos-1)
{
	++i;
	p = p->pNext;	
}

if(NULL==p->pNext || i!=pos-1)//原源代码if(i>pos-1 || NULL == p->pNext)
	return false;

PNODE q = p->pNext;
*pVal = q->data;

p->pNext = p->pNext->pNext;

free(q);
q = NULL;

return true;

}

//在某个节点前插入一个新节点
bool insert_list(PNODE pHead, int pos, int val)
{
int i = 0;

PNODE p = pHead;

//判断插入节点的位置是否在链表的范围内
while(NULL!=p  &&  i < pos-1)// 只有当真&&真时,结果才为真,其它都为假,
{
	++i;            //第一次循环,i=1, 
	p = p->pNext;  //第一次循环,p存放第一个节点的地址
				   /*
				   //i和节点的值改变轨迹
				   printf("第%d循环\n",i);
				   printf("i = %d\n",i);
				   printf("p->data = %d\n", p->data);
	*/		
}
/*
1.当第pos节点在链表中时,在1!<pos-1时,终止循环
2.当第pos节点在尾节点后时,在NULL == p时,终止循环
3.当p指向链表尾节点时,p的值不为空
4.当第pos节点为尾节点后一个节点时,可以插入
*/

/*
当NULL == p时,循环结束,当i < pos-1时,循环结束,i < pos-1功能是当p为pos前一个节点时,
结束循环,插入第pos个节点,需要的是pos前一个节点的指针域
*/



if(NULL==p || i>pos-1 )  //当假||假时,才为假,其它都为真
	return false;  //当插入节点的位置不在链表的范围内时,终止程序
/*
1.当NULL == p时,第pos节点前不能插入节点,第pos节点已经在尾节点后一个节点后面
2.i的最大值为pos-1
*/

//当if不执行时,p为pos前一个节点,


//使用for循环,当循环到某个节点时,插入新节点
PNODE pNew = (PNODE)malloc(sizeof(NODE));  //建立新节点
PNODE q;  //功能:临时存放原第pos个节点的地址

if(NULL == pNew)
{
	printf("内存分配失败,终止程序!\n");
	exit(-1);
}

pNew->data = val;

q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;

return true;

}

//对链表进行排序,从小到大
void sort_list(PNODE pHead)
{
int i,t,j;
int len = length_list(pHead);//把链表的长度赋给len

PNODE q,p;  //创建新链表,为原链表的数据域内数值交换做临时存放和交换条件设定做准备


for(i = 1,p = pHead->pNext; i < len; ++i,p = p->pNext)
{
/*
把原链表指针域的地址赋给p,每次循环都把下一个节点的地址赋给现节点,
更新下一个for循环中q的赋值,p = p->pNext的功能是把已和全部节点比过大小的节点剔除掉,
然后从下一个节点开始和其它剩余的全部节点比较大小
*/
	
	for(t = i,q = p->pNext; t < len; ++t, q = q->pNext)
	{
	/*
	t = i的功能是保证循环起点的准确
	*/
		
		if(p->data > q->data)
		{
			
			j = q->data;//j的功能是当作链表数值交换的中间站点,临时存放交换链表的值
			q->data = p->data;
			p->data = j;
			
			/*
			两个链表的节点不能直接赋值,避免丢失其中一个节点的值,造成两个节点的值相等.
			产生对换数值失败
			*/
			
		}
		
	}
	
	
}


printf("链表节点数值从小到大排序分别是:\n");
return;

}

//求链表长度
int length_list(PNODE pHead)
{
int len = 0;

PNODE p = pHead->pNext;//把头节点指针域的地址赋给p

while(NULL != p)// p存放着链表节点指针域的地址,节点指针域的地址为空时,该节点为尾节点,终止该循环
{
	++len;
	p = p->pNext;//把下个节点的指针域地址赋给现节点p,使p指向下一节点
}

return len;

}

//判断链表是否为空
bool is_empty(PNODE pHead)
{
if(NULL == pHead->pNext)
return true;//返回的结果为真,true与bool结合使用
else
return false;//返回的结果为假,false与bool结合使用
}

//链表输出
void traverse_list(PNODE pHead)
{
int i = 1;

PNODE p = pHead->pNext;//把头节点指针域的地址赋给p

while(NULL != p)// p存放着链表节点指针域的地址,节点指针域的地址为空时,该节点为尾节点,终止该循环
{
	printf("链表第%d个节点的值为:%d\n", i,p->data );
	
	p = p->pNext; //把下个节点的指针域地址赋给现节点p,使p指向下一节点
	
	++i;
	
}


return;

}

//创建链表
PNODE create_list()
{
int len;//临时存放链表的长度
int val;//临时存放链表的值
int i;

PNODE pHead = (PNODE)malloc(sizeof(NODE));//创建链表的头节点
if(NULL == pHead)//判断链表头节点是否创建成功
{
	printf("内存分配失败,终止程序!\n");
	exit(-1);
}


PNODE pTail = pHead;//创建尾节点,并把头节点的地址赋给原始尾节点,
//使头节点和尾节点关联在一起,方便插入新节点
//pTail->pNext 等价于 pHead->pNext
pTail->pNext = NULL;//尾节点指针域初始化

printf("请输入链表长度: ");
scanf("%d",&len);
printf("\n");

for(i = 0; i < len; ++i)
{
	printf("请输入第%d个链表的值为: ", i+1);
	scanf("%d", &val);
	
	PNODE pNew = (PNODE)malloc(sizeof(NODE));//创建链表新节点,并动态存储,仅创建一个新节点
	pNew->data = val;        //新节点数据域赋值
	
	pTail->pNext  = pNew;   //第一次循环把新节点的地址赋给头节点的指针域
	//后面循环把新节点的地址赋给上一节点的指针域
	pNew->pNext =NULL;     //新节点指针域初始化
	pTail = pNew;         //第一次循环,把新节点的地址赋给原尾节点,使PNODE pTail 等价于
	// PNODE pNew ; 后面循环把新节点赋给上一节点,更新尾节点pTail
	// 数据域的值,并使新节点等价于尾节点pTail
	
	
	
}

return pHead;  //返回头节点地址

}

posted @ 2020-08-18 19:59  星空0125  阅读(240)  评论(0)    收藏  举报