数据结构之------非循环单链表的 基础冒泡排序算法实现 ( C Language )

关于C语言版的一些算法实现,例如二叉树的各种算法在很多应用里面比较重要(最短路径什么的).但是计算机发展到今天,很多软件方面的东西已经集成在了各种库中,没有一些很详细的算法介绍(这里要再次膜拜一下严老师和国内外一些把这些原理实现的大牛),还有一些原理的理解,上层建筑的由来可能有些和我一样的朋友,一开始也是比较模糊的,但是如果真的可以理解这些稍微底层点的东西,会对后面的深造有很大的帮助,这些主要是一些数学方面的思想,一些逻辑上面的思想,还有一小部分是运算方面的内容,笼统的说,算法就是数学上面的东西,数据结构是定义了主观上的规则,客观逻辑加上主观的规则,事情就变得很nice了.

1. 初始化线性表(这里说的是链表,数组就不予讨论了):  头插法,尾插法还是很需要了解的,毕竟比较重要,这里只使用一个来实现

PNODE create_list(void)
{	
	int i,tmp,Len;  //需要用的一些整型变量;			
	printf("请输入青青草原上羊的个数:\n");//这里用羊,因为羊是不连续的,有可能会生小羊,也有一部分羊会GG(故用羊来代替)
	scanf_s("%d",&Len);
	PNODE pHead = (PNODE)malloc(sizeof(NODE)); // head pointer definition ,这里需要思考一下为什么不是通过NODE 来定义,如果是的话,会有什么结果
	pHead->Data = NULL;
	PNODE pTail = pHead;  //生成节点pTail
	pTail->Pointer = NULL;//尾节点自己的指针域清空
	for (i=0; i < Len; i++)
	{
		printf("请输入第%d个羊数据域的值:",i+1);
		scanf_s("%d",&tmp);
		PNODE pBody = (PNODE)malloc(sizeof(NODE));
		pBody->Data = tmp;
		pTail->Pointer = pBody;
		pBody->Pointer = NULL;
		pTail = pBody;//被循环赋值	
	}
	/*if (pTail->Pointer != NULL)
		printf("尾指针不是空,生成有问题!");
	else
		printf("尾指针是空,新尾巴生成成功!");
	if (pTail->Data == NULL)
	{
		printf("尾指针数据域为空");
	}*/
	return pHead;
}

2. 下面需要解决排序问题,今天说一个简单的冒泡排序,其中有一两个trick需要注意一下:(要利用p的重新刷新来解决循环的起点问题,不只是简单的嵌套循环,如果没想到刷新p的话,这里会变成只能循环一次或者直接出错,系统不认的bug)

void sort_list_with_buble(PNODE eagle)
{
	int length = length_of_the_list(eagle);
	int i,j,tmp,cnt=0;
	PNODE p = eagle->Pointer;
	PNODE q=p;
	/*t->Data == NULL;
	t->Pointer == NULL;*/
	for (i = 0; i < length - 1; i++,p=q)
	{
		for (j = 0; j < length - 1; j++,p=p->Pointer)
		{
			if (p->Data > p->Pointer->Data)
			{
				tmp = p->Data;//冒泡排序算法核心交换
				p->Data = p->Pointer->Data;
				p->Pointer->Data = tmp;
			}
		/*	while (j == length - 2)
			{
				printf("ok\n");
				PNODE pNew = (PNODE)malloc(sizeof(NODE));
				pNew = eagle->Pointer;
				p = pNew;
				printf("ok??\n");
				break;
			}*/

		}
		
		
		/*for (j = 0, q; j < length - 1; j++, q = q->Pointer)
		{
			if (q->Data > q->Pointer->Data)
			{
				tmp = q->Data;
				q->Data = q->Pointer->Data;
				q->Pointer->Data = tmp;
			}
			
		}*/
	}
	/*printf("从小到大排序过后的链表中节点数据域元素展示: \n");
	for (i = 0; i < length; i++)
	{
		printf("%d ",p->Data);
		p = p->Pointer;	
	}
	printf("\n 我一定会回来的!\n");
	*/
}

这里利用q的刷新来重新定义p的使用,很简单的方法就可以使p能再次利用起来,从而巧妙地达到了循环的目的,代码是非常的简单,但是主要不在代码,这种思想我觉得还是很重要的,所以写下来,每次看看都不一样,温故而知新,希望更多的人可以彻底理解这种思想,概念性的东西,下面会加上完整代码.

3. 完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
#include <windows.graphics.display.h>

typedef struct Xbox
{
	int Data;
	struct Xbox * Pointer;

}NODE,*PNODE;

PNODE create_list(void);//链表的创建
void travel_list(PNODE);//链表的遍历
void insert_in(PNODE ,int ,int);//插入一个node
void remove_list();//移除一个node
void sort_list_with_buble(PNODE); 
void del_node(PNODE,int,int *);
bool is_full();
bool is_empty(PNODE);
int  length_of_the_list(PNODE);

void main()
{
	PNODE puma=NULL;
	puma=create_list();//创建链表函数执行过程
	travel_list(puma);//遍历一遍执行过程
	int len=length_of_the_list(puma);//求链表长度函数执行过程
	printf("链表长度为:%d \n",len);
	sort_list_with_buble(puma);
	travel_list(puma);//遍历一遍执行过程
}

PNODE create_list(void)
{	
	int i,tmp,Len;  //需要用的一些整型变量;			
	printf("请输入青青草原上羊的个数:\n");
	scanf_s("%d",&Len);
	PNODE pHead = (PNODE)malloc(sizeof(NODE)); // head pointer definition; 真正的头结点定义应该是:  NODE  Head  ;这里只是头指针并不是头结点.有指针必然有一个对应的实体存在,只不过是否命名的问题.,这就是整个数据结构中节点生成的原理:利用一个分配了内存的同构结构体指针变量来生成一个节点(刚分配时候是未命名的节点,但是也不太需要命名,因为不需要,这里没有一个实体节点名但是实现了功能,很妙的思考!)
	pHead->Data = NULL;
	PNODE pTail = pHead;  //把头结点当成尾节点
	pTail->Pointer = NULL;//尾节点自己的指针域清空
	for (i=0; i < Len; i++)
	{
		printf("请输入第%d个羊数据域的值:",i+1);
		scanf_s("%d",&tmp);
		PNODE pBody = (PNODE)malloc(sizeof(NODE));
		pBody->Data = tmp;
		pTail->Pointer = pBody;
		pBody->Pointer = NULL;
		pTail = pBody;//把新生成的节点变成尾巴,把头结点也可以看成尾节点,定义一个尾巴的思想很巧妙,把新的节点利用循环变成尾巴来生成下一个节点.	
	}
	return pHead;
}
void travel_list(PNODE dog)
{
	/*for (int i = 1; i <= 5;i++)
	{
		printf("%d \n",dog->Data);
	}*/
	PNODE cat = dog->Pointer;/
	printf("链表元素展示:");//貌似系统会自动遍历所有的节点然后把不空的节点内容输送到显示器上.
	while (cat != NULL)
	{
		printf("%d ", cat->Data);//三角转移型存储
		cat = cat->Pointer;
	}                      
	printf("\n");        
}
bool is_empty(PNODE cat)
{
	//PNODE eagle = cat->Pointer;
	//if (eagle->Data == NULL)
	//{ 
	//	printf("eagle节点数据域都为空!!!");
	//	return true;
	//}
	//else
	//	return false;
	if (cat->Pointer == NULL)
		return true;//默认cat就是上面指的那个pHead,当成首节点来看.
	else
		return false;
}
int  length_of_the_list(PNODE fish)
{
	PNODE p = fish->Pointer;
	int cnt = 0;
	
	for (p; p != NULL;cnt++)
	{
		p = p->Pointer;
	}
	/*printf("此链表长度为: %d\n",cnt);*/
	return cnt;
}
void sort_list_with_buble(PNODE eagle)
{
	int length = length_of_the_list(eagle);
	int i,j,tmp,cnt=0;
	PNODE p = eagle->Pointer;
	PNODE q=p;
	for (i = 0; i < length - 1; i++,p=q)
	{
		for (j = 0; j < length - 1; j++,p=p->Pointer)
		{
			if (p->Data > p->Pointer->Data)
			{
				tmp = p->Data;//冒泡排序算法核心交换
				p->Data = p->Pointer->Data;
				p->Pointer->Data = tmp;
			}
		/*	while (j == length - 2)
			{
				printf("ok\n");
				PNODE pNew = (PNODE)malloc(sizeof(NODE));
				pNew = eagle->Pointer;
				p = pNew;
				printf("ok??\n");
				break;
			}*/

		}
		
		
		/*for (j = 0, q; j < length - 1; j++, q = q->Pointer)
		{
			if (q->Data > q->Pointer->Data)
			{
				tmp = q->Data;
				q->Data = q->Pointer->Data;
				q->Pointer->Data = tmp;
			}
			
		}*/
	}
	/*printf("从小到大排序过后的链表中节点数据域元素展示: \n");
	for (i = 0; i < length; i++)
	{
		printf("%d ",p->Data);
		p = p->Pointer;	
	}
	printf("\n 我一定会回来的!\n");
	*/
}

猜你喜欢

转载自blog.csdn.net/yang7654/article/details/79456506