单链表(二):如何实现单链表的排序、逆置(逆序)

1、单链表的排序

示例代码如下:

#include<iostream>
using namespace std;

///单链表结构体:结点
typedef struct student
{
    int data;				//结点中的数据
    struct student *next;	//指向链表下一个结点的指针
}node;

node *head;	//头结点指针
int index;	//链表长度

///建立单链表
void *create()
{
    node *p,*s;	//增加结点的位置指针、要增加结点的指针
    int x,cycle=1;		//x是结点中的数据,若为0代表创建结束;cycle是循环控制变量
    head=(node*)malloc(sizeof(node)); //动态分配,建立头节点
    p=head;
    while(cycle)
    {
        printf("Please input the data:");
        scanf("%d",&x);
        if(x!=0)
        {
            s=(node*)malloc(sizeof(node));	//动态分配,每次新建一个节点
            s->data=x;						//将数据存入该结点
//			printf("%d\n",s->data);			//查看该结点中的数据是否正确
            p->next=s;						//连接头指针与当前结点
            p=s;							//并将头指针指向当前结点的指针,即下一个结点的地址
        }
        else
        {
            cycle=0;
        }
    }

    p->next=NULL;		//最后一个结点为空指针(必须)

//	head=head->next;	//创建完毕单链表,头结点指针回去
//	printf("\n   yyy   %d",head->data);	//打印第一个结点中的数据,用于验证

    return head;		//返回根结点
}

///遍历单链表(单链表打印),同时测长
//注:链表无法从反方向进行遍历
void traverse(node *head)
{
	node *p;
	index=0;
	if(head->next==NULL)
	{
		printf("Link is empty!\n");
		return;
	}
	p=head->next;
	while(p!=NULL)//遍历链表
	{
		printf("The %dth node is:%d\n",++index,p->data);//打印元素,亦可计算链表长度(index)
		p=p->next;//进入下一个结点
	}
	printf("\n该链表长度为:%d\n\n",index);
}

///单链表的排序
void *sort(node *head)
{
	node *p;
	int n=index;	//链表长度
	int temp;
	if(head==NULL || head->next==NULL)
		return head;

	p=head->next;	//p指向结点1,可以得到结点1的数据

	for(int j=1;j<n;j++) //冒泡排序
	{
		p=head->next;	//每次冒泡过程完毕后,必须返回结点1
		for(int i=n-1;i>=j;i--)	//一次冒泡过程
		{
			if( (p->data) > (p->next->data) )	//从小到大排序
			{
				temp=p->data;
				p->data=p->next->data;
				p->next->data=temp;
			}
			p=p->next;
		}
	}

	p=head->next;	//要打印排序好的链表,必须从头开始打印,也是遍历的一个过程
	//打印出排好序的链表(从小到大)
	for(int m=0;m<n;m++)
	{
		printf(" %d",p->data);
		p=p->next;

	}
	cout<<endl;
}
int main()
{
	cout<<"/***** 单链表的创建 *****/"<<endl;
	create();		//单链表的创建

	cout<<endl<<"/***** 单链表的遍历与测长 *****/"<<endl;
	traverse(head);	//单链表的遍历与测长

	cout<<endl<<"/***** 单链表的排序 *****/"<<endl;
	sort(head);	//单链表的排序

	return 0;
}

测试结果如图:

2、单链表的逆置(逆序)

单链表的逆置有2种方法,分别如下。

方法一:

基本思想:类似于冒泡法,但是不用比较数据大小,即可。

方法二:

基本思想:

(1)、单链表的模型如下图:

(2)、进行单链表的逆序,首先要让p2的next指向p1,如下图:

(3)、再由p1指向p2,p2指向p3,如下图:

然后重复p2的next指向p1,p1指向p2,p2指向p3。

完整的示例代码如下:

#include<iostream>
using namespace std;

///单链表结构体:结点
typedef struct student
{
    int data;				//结点中的数据
    struct student *next;	//指向链表下一个结点的指针
}node;

node *head;	//头结点指针
int index;	//链表长度

///建立单链表
void *create()
{
    node *p,*s;	//增加结点的位置指针、要增加结点的指针
    int x,cycle=1;		//x是结点中的数据,若为0代表创建结束;cycle是循环控制变量
    head=(node*)malloc(sizeof(node)); //动态分配,建立头节点
    p=head;
    while(cycle)
    {
        printf("Please input the data:");
        scanf("%d",&x);
        if(x!=0)
        {
            s=(node*)malloc(sizeof(node));	//动态分配,每次新建一个节点
            s->data=x;						//将数据存入该结点
//			printf("%d\n",s->data);			//查看该结点中的数据是否正确
            p->next=s;						//连接头指针与当前结点
            p=s;							//并将头指针指向当前结点的指针,即下一个结点的地址
        }
        else
        {
            cycle=0;
        }
    }

    p->next=NULL;		//最后一个结点为空指针(必须)

//	head=head->next;	//创建完毕单链表,头结点指针回去
//	printf("\n   yyy   %d",head->data);	//打印第一个结点中的数据,用于验证

    return head;		//返回根结点
}

///遍历单链表(单链表打印),同时测长
//注:链表无法从反方向进行遍历
void traverse(node *head)
{
	node *p;
	index=0;
	if(head->next==NULL)
	{
		printf("Link is empty!\n");
		return;
	}
	p=head->next;
	while(p!=NULL)//遍历链表
	{
		printf("The %dth node is:%d\n",++index,p->data);//打印元素,亦可计算链表长度(index)
		p=p->next;//进入下一个结点
	}
	printf("\n该链表长度为:%d\n\n",index);
}

///单链表的排序
void *sort(node *head)
{
	node *p;
	int n=index;	//链表长度
	int temp;
	if(head==NULL || head->next==NULL)
		return head;

	p=head->next;	//p指向结点1,可以得到结点1的数据

	for(int j=1;j<n;j++) //冒泡排序
	{
		p=head->next;	//每次冒泡过程完毕后,必须返回结点1
		for(int i=n-1;i>=j;i--)	//一次冒泡过程
		{
			if( (p->data) > (p->next->data) )	//从小到大排序
			{
				temp=p->data;
				p->data=p->next->data;
				p->next->data=temp;
			}
			p=p->next;
		}
	}

	p=head->next;	//要打印排序好的链表,必须从头开始打印,也是遍历的一个过程
	//打印出排好序的链表(从小到大)
	for(int m=0;m<n;m++)
	{
		printf(" %d",p->data);
		p=p->next;

	}
	cout<<endl;
}

///单链表的逆置:方法一
/*
注:链表无法从反方向进行遍历
方法一的基本思想:类似于冒泡法,但是不用比较数据大小即可。
*/

void *reverse1(node *head)
{
	node *p;
	int n=index;	//链表长度
	int temp;
	if(head==NULL || head->next==NULL)
		return head;

	p=head->next;	//p指向结点1,可以得到结点1的数据

	for(int j=1;j<n;j++)
	{
		p=head->next;
		for(int i=n-1;i>=j;i--)
		{

			temp=p->data;
			p->data=p->next->data;
			p->next->data=temp;
			p=p->next;
		}
	}

	p=head->next;

	//打印出逆置后的链表
	for(int m=0;m<index;m++)
	{
		printf(" %d",p->data);
		p=p->next;
	}
}

///单链表的逆置:方法二
void *reverse2(node *head)
{
	node *p1,*p2,*p3;
	if(head==NULL || head->next==NULL)
		return head;

	p1=head;	//初始化p1是根结点
    p2=p1->next;//初始化p2是结点1
    while(p2)//当前结点的下一个结点是否为空
    {
        p3=p2->next;
        p2->next=p1;
        p1=p2;
        p2=p3;
    }
    head->next=NULL;
    head=p1;	

	//打印出逆置后的链表
	for(int m=0;m<index;m++)
	{
		printf(" %d",p1->data);
		p1=p1->next;
	}
	cout<<endl;
}

int main()
{
	cout<<"/***** 单链表的创建 *****/"<<endl;
	create();		//单链表的创建

	cout<<endl<<"/***** 单链表的遍历与测长 *****/"<<endl;
	traverse(head);	//单链表的遍历与测长

//	cout<<endl<<"/***** 单链表的排序 *****/"<<endl;
//	sort(head);	//单链表的排序

	cout<<endl<<"/***** 单链表的逆置:方法一 *****/"<<endl;
	reverse1(head);	//单链表的逆置:方法一

	cout<<endl<<"/***** 单链表的逆置:方法二 *****/"<<endl;
	reverse2(head);	//单链表的逆置:方法二

	return 0;
}

测试结果如下图:

时间: 2024-10-26 05:42:57

单链表(二):如何实现单链表的排序、逆置(逆序)的相关文章

用C语言计算一个单链表的长度,单链表的定义如下:要求使用递归,不得出现循环。

问题描述 用C语言计算一个单链表的长度,单链表的定义如下:要求使用递归,不得出现循环. 用C语言计算一个单链表的长度,单链表的定义如下:要求使用递归,不得出现循环. 解决方案 如果链表有环,永远算不出来 只能假定,这个链表不是环形链表,也没有环 简单事情用递归做是低效率的,即便学习递归,也是不必要的 递推, 可以用递归实现 也可以用迭代实现 前者无循环,后者有 解决方案二: int listLength(List *l) { if(l->next!=NULL) { l=l->next; ret

c语言-编写一程序,将带头结点的单链表拆成一个奇数链表和一个偶数链表

问题描述 编写一程序,将带头结点的单链表拆成一个奇数链表和一个偶数链表 要求用C语言来做!! 解决方案 http://zhidao.baidu.com/link?url=5XqMAQVb1yS0vaNF3QXC9fQPICC-JgqN0lisYvRQHwzYF8jb3ek3ouh_2TG3NKa4eanjSv4illaaV1znE-nkuq 解决方案二: BaiDu:将带头结点的单链表拆成一个奇数链表和一个偶数链表 你会得到很多你想要的. 解决方案三: 这个简单,可以看看面试宝典

c语言 数据结构-单链表的就地逆置 辅助空间为O(1)

问题描述 单链表的就地逆置 辅助空间为O(1) 求大神给个单链表的就地逆置 要不开拓辅助空间 原谅我没有C币 解决方案 struct Node{ int value; Node *next; }; void reverse(Node* head){ Node *prev, *cur, *next; cur = head; prev = NULL; while(cur != NULL){ next = cur->next; cur->next = prev; prev = cur; cur =

创建单链表并利用栈将其逆置...小白求大神帮改一下多谢。

问题描述 创建单链表并利用栈将其逆置...小白求大神帮改一下多谢. 建立单链表时输入链表数据(字符数据)以'#'号结束. #include #include #define M 20 typedef struct { char data[M]; int top; }SeqStack; typedef struct lnode { char data; struct lnode*next; }LNode,*LinkList; SeqStack*Init_SeqStack() { SeqStack*

数据结构实践——单链表:逆置、连接与递增判断

本文针对数据结构基础系列网络课程(2):线性表的实践项目. [项目 - 单链表算法](程序中利用了已经实现的单链表算法,头文件LinkList.h及其中函数的实现见单链表算法库) 1.设计一个算法,将一个带头结点的数据域依次为a1,a2,-,an(n≥3)的单链表的所有结点逆置,即第一个结点的数据域变为an,-,最后一个结点的数据域为a1.实现这个算法,并完成测试. [参考解答] (程序中利用了已经实现的单链表算法,头文件LinkList.h及其中函数的实现见单链表算法库) #include <

数据结构实验之链表二:逆序建立链表

数据结构实验之链表二:逆序建立链表 Time Limit: 1000MS Memory Limit: 65536KB Problem Description 输入整数个数N,再输入N个整数,按照这些整数输入的相反顺序建立单链表,并依次遍历输出单链表的数据. Input 第一行输入整数N;: 第二行依次输入N个整数,逆序建立单链表. Output 依次输出单链表所存放的数据. Example Input 10 11 3 5 27 9 12 43 16 84 22 Example Output 22

轻松玩转花样表单(二)花样表单

二.表单外观的美化 很多时候,我们仅仅为了实现数据采集这个功能来使用表单,常看到的表单都是"千人一面".毫无生气,本专题尝试着来改变这一现象,试图赋予表单一个丰富多彩的面貌.表单的外观,也是最为直接的花样,可以通过改变它来实现特效,本文分两个出发点来讲述:CSS魔法和图像魔法. 1.CSS魔法 CSS,就是大家知道的层叠样式单,它可以定义页面元素的外观,包括字体样式.背景颜色和图像样式.边框样式.补白样式.边界样式等等,下面就从这几个方面出发,讨论怎样将CSS应用到表单中,彻底美化它!

jquery构建功能型表单(二)

在构建功能型表单(一) 中介绍了一些适用于用户进行文本性输入的表单功能. 然而,有时候表单 中的内容也会以数字为主. 当处理作为表单内容的数字值时,也可以实现另外几种表单增强功能. 数字表单的典型代表就是购物车.在购物车表单中,应该允许用户更新购买的商品数量,同时,也要 为用户提供价格和总金额的数字反馈. 构建功能行表单(二) 1.在操作表单前 先为表格应用标准的行条纹效果,美化一下表格的外观 Js代码 var stripe = function(){ $("#cart tbody tr:vis

activiti自定义流程之自定义表单(二):创建表单

注:环境配置:activiti自定义流程之自定义表单(一):环境配置 在上一节自定义表单环境搭建好以后,我就正式开始尝试自己创建表单,在后台的处理就比较常规,主要是针对ueditor插件的功能在前端进行修改. 由于自己的前端相关技术太渣,因此好多东西都不会用,导致修改实现的过程也是破费了一番功夫,头皮发麻了好几天. 既然是用别人的插件进行修改,那么我想如果只是单独的贴出我修改后的代码,可能没有前后进行对比好理解,因此这里就把原代码和修改后的同时对比着贴出,以便于朋友们能从对比中更快的得到启发.