导航:首页 > 源码编译 > c单链表排序算法

c单链表排序算法

发布时间:2025-03-19 08:30:21

A. 计算机二级c语言考些什么

公共基础知识
基本要求
1. 掌握算法的基本概念。
2. 掌握基本数据结构及其操作。
3. 掌握基本排序和查找算法。
4. 掌握逐步求精的结构化程序设计方法。
5. 掌握软件工程的基本方法,具有初步应用相关技术进行软件开发的能力。
6. 掌握数据的基本知识,了解关系数据库的设计。
考试内容
一、 基本数据结构与算法
1. 算法的基本概念;算法复杂度的概念和意义(时间复杂度与空间复杂度)。
2. 数据结构的定义;数据的逻辑结构与存储结构;数据结构的图形表示;线性结构与非线性结构的概念。
3. 线性表的定义;线性表的顺序存储结构及其插入与删除运算。
4. 栈和队列的定义;栈和队列的顺序存储结构及其基本运算。
5. 线性单链表、双向链表与循环链表的结构及其基本运算。
6. 树的基本概念;二叉树的定义及其存储结构;二叉树的前序、中序和后序遍历。(前序、中序和后序遍历有考到,每年都有)
7. 顺序查找与二分法查找算法;基本排序算法(交换类排序,选择类排序,插入类排序)。
二、 程序设计基础
1. 程序设计方法与风格。
2. 结构化程序设计。
3. 面向对象的程序设计方法,对象,方法,属性及继承与多态性。
三、 软件工程基础
1. 软件工程基本概念,软件生命周戎概念,软件工具与软件开发环境。
2. 结构化分析方法,数据流图,数据字典,软件需求规格说明书。
3. 结构化设计方法,总体设计与详细设计。
4. 软件测试的方法,白盒测试与黑盒测试,测试用例设计,软件测试的实施,单元测试、集成测试和系统测试。
5. 程序的调试,静态调试与动态调试。
四、 数据库设计基础
1. 数据库的基本概念:数据库,数据库管理系统,数据库系统。
2. 数据模型,实体联系模型及E-R图,从E-R图导出关系数据模型。
3. 关系代数运算,包括集合运算及选择、投影、连接运算,数据库规范化理论。
4. 数据库设计方法和步骤:需求分析、概念设计、逻辑设计和物理设计的相关策略。
考试方式
1、 公共基础的考试方式为笔试,与C语言(VisualBASIC、Visual FoxPro、Java、Access、Visual C++)的笔试部分合为一张试卷。公共基础部分占全卷的30分。
2、 公共基础知识有10道选择题和5道填空题。
C语言程序设计
基本要求
1.熟悉TURBO C集成环境。
2.熟练掌握结构化程序设计的方法,具有良好的程序设计风格。
3.掌握程序设计中简单的数据结构和算法。
4.TURBO C的集成环境下,能够编写简单的C程序,并具有基本的纠错和调试程序的能力。
考试内容
一、C语言的结构
1.程序的构成,MAIN函数和其他函数。
2.头文件,数据说明,函数的开始和结束标志。
3.源程序的书写格式
4.C语言的风格。
二、数据类型及其运算(基础)
1.C的数据类型(基本类型,构造类型,指针类型,空类型)及其定义方法。
2.C运算符的种类、运算优先级和结合性。
3.不同类型数据间的转换与运算。
4.C表达式类型(赋值表达式、算术表达式、关系表达式、逻辑表达式、条件表达式、逗号表达式)和求值规则。
三、基本语句(基础)
1.表达式语句,空语句,复合语句。
2.数据的输入和输出,输入输出函数的调用。
3.复合语句。
4.GOTO语句和语句标号的使用。(这个了解即可)
四、选择结构程序设计
1.用if语句实现选择结构。(基础)
2.用switch语句实现多分支选择结构。(笔试有)
3.选择结构的嵌套。
五、循环结构程序设计 (基础)
1.for 循环结构。
2.while和do while循环结构。
3.continue语句和break语句。
4.循环的嵌套。(基础)
六、数组的定义和引用
1.一维数组和多维数组的定义、初始化和引用。
2.字符串与字符数组。
七、函数 (基础)
1.库函数的正确调用。
2.函数的定义方法。
3.函数的类型和返回值。
4.形式参数与实在参数,参数值的传递。
5.函数的正确调用,嵌套调用,递归调用。
6.局部变量和全局变量。
7.变量的存储类别(自动、静态、寄存器、外部),变量的作用域和生存期。
8.内部函数与外部函数。
八、编译预处理 (基础,笔试有考到宏替换)
1.宏定义:不带参数的宏定义;带参数的宏定义。
2.“文件包含”处理。
九、指针 (这个很重要,上机题有这方面的)
1.指针与指针变量的概念,指针与地址运算符。
2.变量、数组、字符串、函数、结构体的指针以及指向变量、数组、字符串、函数、结构体的指针变量。通过指针引用以上各类型数据。
3.用指针作函数参数。
4.返回指针值的指针函数。
5.指针数组,指向指针的指针,MAIN函数的命令行参数。
十、结构体(即“结构”)与共用体(即“联合”)
1.结构体和共用体类型数据的定义方法和引用方法。
2.用指针和结构体构成链表,单向链表的建立、输出、删除与插入。
十一、位运算
1.位运算符的含义及使用。
2.简单的位运算。
十二、文件操作(了解,上级题有,只要知道什么意思就行了)
只要求缓冲文件系统(即高级磁盘I/O系统),对非标准缓冲文件系统(即低级磁盘I/O系统)不要求。
1.文件类型指针(FILE类型指针)。
2.文件的打开与关闭(fopen,fclose)。
3.文件的读写(fputc,fgetc,fputs,fgets,fread,frwite,fprintf,fscanf函数),文件的定位(rewind,fseek函数)。
PS:分为笔试和机试两部份,机试有三道题,一道改错,一道补充,一道综合,笔试中有30分公共基础知识,为数据结构,数据库,网络和电脑常识方面的问题,有70分选择题,30分填空题,难点为数组,指针,也为重点
全国计算机等级考试调整方案
关于二级
考试科目:新增二级Delphi语言程序设计,加上原有的二级C等六个科目,二级共七个科目。二级科目分成两类,一类是语言程序设计(C、C++、Java、Visual Basic、Delphi),另一类是数据库程序设计(Visual FoxPro、Access)。
考核内容:二级定位为程序员,考核内容包括公共基础知识和程序设计。所有科目对基础知识作统一要求,使用统一的公共基础知识考试大纲和教程。二级公共基础知识在各科笔试中的分值比重为30%(30分)。程序设计部分的比重为70%(70分),主要考查考生对程序设计语言使用和编程调试等基本能力。
考试形式:二级所有科目的考试仍包括笔试和上机考试两部分。二级C笔试时间由120分钟改为90分钟,上机时间由60分钟改为90分钟。所有二级科目的笔试时间统一为90分钟,上机时间统一为90分钟。
系统环境:二级各科目上机考试应用软件为:中文专业版Access 2000、中文专业版Visual Basic 6.0、中文专业版Visual FoxPro 6.0、Visual C++ 6.0,二级C上机应用软件由Turbo C 2.0改为 Visual C++6.0,二级Java由现在的Java JDK 1.4.2改为专用集成开发环境“NetBeans 中国教育考试版2007”(有关网站将提供免费下载),二级Delphi使用Delphi7.0版本。

B. 拓扑排序

1、堆栈

栈是一种特殊的线性表,插入或删除栈元素的运算只能在表的一端进行,称运算的一端为栈顶,另一端称为栈底。队列也是一种特殊的线性表(基本操作都是线性操作的子集)。

特点:后进先出

栈又称为“后进先出”的线性表,简称LIFO表。

栈的链式实现是以链表作为栈的存储结构,并在这种存储结构上实现栈的基本运算。栈的链式实现称为链栈。

2、有向无环图

描述含有公共子式的表达式的有效工具;

描述一项工程或系统的进行过程的有效工具。

3、一些概念

通常我们把计划、施工过程、生产流程、程序流程等都当成一个工程,一个大的工程常常被划分成许多较小的子工程,这些子工程称为活动。这些活动完成时,整个工程也就完成了。

我们用一种有向图来表示这些工程、计划等,在这种有向图中,顶点表示活动,有向边表示活动的优先关系,这种用顶点表示活动,用弧来表示活动间的优先关系的有向图叫做顶点表示活动的网络(ActireOnVertices)简称为AOV网。

拓扑排序:

假设G=(V,E)是一个具有n个顶点的有向图,V中顶点序列vl,v2,…,vn称做一个拓扑序列(TopologicalOrder),当且仅当该顶点序列满足下列条件:若在有向图G中存在从顶点vi到vj的一条路径,则在顶点序列中顶点vi必须排在顶点vj之前。通常,在AOV网中,将所有活动排列成一个拓扑序列的过程叫做拓扑排序掘亏(TopologicalSort)。

在AOV网中不应该出现有向环。因为环的存在意味着某项活动将以自己为先决条件,显然无法形成拓扑序列。

判定网中是否存在环的方法:对有向图构造其顶点的拓扑有序序列,若网中所有顶点都出现在它的拓扑有序序列中,则该AOV网中一定不存在环。

4、拓扑排序的算法思想

输入AOV网络。令n为顶点个数。

(1)在AOV网络中选一个没有直接前驱的顶点,并输出之;

(2)从图中删去该顶点,同时删去所有它发出的有向边;

重复以上步骤,直到全部顶点均已输出,拓扑有序序列形成,拓扑排序完成;或图中还有未输出的顶点,但已跳出处理循环。这说明图中还剩下一些顶点,它们都有直接前驱,再也找不到没有前驱的顶点了。这时AOV网络中必定存在有向环。

5、拓扑排序算法的C语言描述

在实现拓扑排序的算法中,采用邻接表作为有向图的存储结构,每个顶点设置一个单链表,每个单链表有一个表头结点,在表头结点中增加一个存放顶点入度的域count,这些表头结点构成一个数组。

为了避免重复检测入度为0的点,另设一栈存放所有入度为0的点。

对于有n个顶点和e条边的有向图而言,for循环中建立入度为0的顶点栈时间为O(n);若在拓扑排序过程中不出现有向环,则判扰神每个顶点出栈、入栈和入度减1的操作在while循环语句中均执行e次,因此拓扑排序总的时间花费为O(n+e)。

6、拓扑排序算法的C语言实现

#include"stdio.h"

#defineMAX_VERTEX_NUM20

#include"conio.h"

#include"stdlib.h"

#defineSTACK_INIT_SIZE16

#defineSTACKINCREMENT5

typedef intSElemType;

typedefcharVertexType;

typedefstruct

{

SElemType*base;

SElemType*top;

intstacksize;

}SqStack;

//我们依然用邻接表来作图的存储结构

typedefstructArcNode{

intadjvex;

struct李历ArcNode*nextarc;

intinfo;

}ArcNode; //表结点类型

typedefstructVNode{

VertexTypedata;

intcount;

ArcNode*firstarc;

}VNode,AdjList[MAX_VERTEX_NUM];//头结点

typedefstruct{

AdjListvertices; //邻接表

intvexnum,arcnum;

}ALGraph;

intInitStack(SqStack&S)

{

S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));

if(!S.base)exit(-1);

S.top=S.base;

S.stacksize=STACK_INIT_SIZE;

return1;

}//InitStack

intPush(SqStack&S,SElemTypee)

{

if((S.top-S.base)>=S.stacksize)

{

S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));

if(!S.base)exit(-1);

S.top=S.base+S.stacksize;

S.stacksize+=STACKINCREMENT;

}//if

*(S.top)=e;

S.top++;

return1;

}//Push

intPop(SqStack&S,SElemType&e)

{

if(S.top==S.base)return0;

--S.top;

e=*S.top;

return1;

}//Pop

intStackEmpty(SqStack&S)

{

if(S.top==S.base)return1;

elsereturn0;

}//StackEmpty

intLocateVex(ALGraphG,charu)

{

inti;

for(i=0;i<G.vexnum;i++)

{if(u==G.vertices[i].data)returni;}

if(i==G.vexnum){printf("Erroru! ");exit(1);}

return0;

}

voidCreateALGraph_adjlist(ALGraph&G)

{

inti,j,k,w;

charv1,v2,enter;

ArcNode*p;

printf("Inputvexnum&arcnum: ");

scanf("%d",&G.vexnum);

scanf("%d",&G.arcnum);

printf("InputVertices(以回车隔开各个数据): ");

for(i=0;i<G.vexnum;i++)

{ scanf("%c%c",&enter,&G.vertices[i].data);//注意点,解说

G.vertices[i].firstarc=NULL;

}//for

printf("InputArcs(v1,v2,w)以回车分开各个数据: ");

for(k=0;k<G.arcnum;k++)

{

scanf("%c%c",&enter,&v1);

scanf("%c%c",&enter,&v2);

//scanf("%d",&w);

i=LocateVex(G,v1);

j=LocateVex(G,v2);

p=(ArcNode*)malloc(sizeof(ArcNode));

p->adjvex=j;

//p->info=w;

p->nextarc=G.vertices[i].firstarc;//前插法,即每次都插入到头结点的后面

G.vertices[i].firstarc=p;

printf("Next ");

}//for

return;

}//CreateALGraph_adjlist

voidFindInDegree(ALGraph&G)

{

inti,j;

for(i=0;i<G.vexnum;i++)

{

G.vertices[i].count=0;

}//for

for(j=0;j<G.vexnum;j++)

{

//G.vertices[i].count++;

for(ArcNode*p=G.vertices[j].firstarc;p;p=p->nextarc)

G.vertices[p->adjvex].count++;

}//for

}//FindInDegree

intTopoSort(ALGraph&G)

{

SqStackS;

FindInDegree(G);

InitStack(S);

for(inti=0;i<G.vexnum;i++)

if(G.vertices[i].count==0)Push(S,i);

intcountt=0;

while(!StackEmpty(S))

{

inti,m;

m=Pop(S,i);

printf("%c",G.vertices[i].data);++countt;

for(ArcNode*p=G.vertices[i].firstarc;p;p=p->nextarc)

{ intk;

k=p->adjvex;

if(!(--G.vertices[k].count))Push(S,k);

}//for

}//while

if(countt<G.vexnum)return0;

elsereturn1;

}//TopoSort

intmain()

{

ALGraphG;

CreateALGraph_adjlist(G);

TopoSort(G);

return1;

}

7、malloc函数和realloc函数

realloc:void*realloc(void*block,size_tsize),将block所指存储块调整为大小size,返回新块的地址。如能满足要求,新块的内容与原块一致;不能满足要求时返回NULL,此时原块不变。

malloc:void*malloc(size_tsize):分配一块足以存放大小为size的存储,返回该存储块的地址,不能满足时返回NULL。

C. 采用单链表作存储结构,编写一个采用选择排序算法进行升序排序的函数。 单链表的结构如下:

下面大体介绍一下基本思想:由于是递增的单链表:0->0->0->0 这种结构不能逆向反问;所以直接做操作是很不好实现的;所以我第一步是将两链表的指针反转,这样就使原来两链表由递增序列变成了递减序列;第二步在根据合并排序的思想,将两个链合并; 思路比较简单,你一看因该能明白,我用C++实现了一下想法,代码如下:#include <iostream>using namespace std;const int N = 8;struct Node};void Print(Node* p)while(p); cout << endl;}void Create(Node*& List) }}void Sort(Node*& List) }}void Converse(Node*& List) //将链表中指针逆向,实际上就是将递增序列变为递减序列 List = q; q->next = p;}void Merge(Node*& List1, Node*&List2, Node*& List3) else } //将剩余的直接接过去即可; if(p == 0) tail->next = q; else tail->next = p;}int main()

D. 常见查找和排序算法

查找成功最多要n 次,平均(n+1)/2次, 时间复杂度为O(n)
优点:既适用顺序表也适用单链表,同时对表中元素顺序无要求,给插入带来方便,只需插入表尾即可。
缺点:速度较慢。

改进:在表尾设置一个岗哨,这样不用去循环判断数组下标是否越界,因为最后必然成立。

适用条件:

二分查找的判定树不仅是二叉排序树,而且是一棵理想平衡树。 时间复杂度为O(lbn)

循环实现

递归实现

待排序的元素需要实现 Java 的 Comparable 接口,该接口有 compareTo() 方法,可以用它来判断两个元素的大小关系。

从数组中选择最小元素,将它与数组的第一个元素交换位置。再从数组剩下的元素中选择出最小的元素,将它与数组的第二个元素交换位置。不断进行这样的操作,直到将整个数组排序。

选择排序需要 ~N2/2 次比较和 ~N 次交换,==它的运行时间与输入无关==,这个特点使得它对一个已经排序的数组也需要这么多的比较和交换操作。

从左到右不断 交换相邻逆序的元素 ,在一轮的循环之后,可以让未排序的最大元素上浮到右侧。

在一轮循环中,如果没有发生交换,那么说明数组已经是有序的,此时可以直接退出。

每次都 将当前元素插入到左侧已经排序的数组中 ,使得插入之后左侧数组依然有序。

对于数组 {3, 5, 2, 4, 1},它具有以下逆序:(3, 2), (3, 1), (5, 2), (5, 4), (5, 1), (2, 1), (4, 1),插入排序每次只能交换相邻元素,令逆序数量减少 1,因此插入排序需要交换的次数为逆序数量。

==插入排序的时间复杂度取决于数组的初始顺序,如果数组已经部分有序了,那么逆序较少,需要的交换次数也就较少,时间复杂度较低==。

对于大规模的数组,插入排序很慢,因为它只能交换相邻的元素,每次只能将逆序数量减少 1。希尔排序的出现就是为了解决插入排序的这种局限性,它通过交换不相邻的元素,每次可以将逆序数量减少大于 1。

希尔排序使用插入排序对间隔 h 的序列进行排序。通过不断减小 h,最后令 h=1,就可以使得整个数组是有序的。

希尔排序的运行时间达不到平方级别,使用递增序列 1, 4, 13, 40, ... 的希尔排序所需要的比较次数不会超过 N 的若干倍乘于递增序列的长度。后面介绍的高级排序算法只会比希尔排序快两倍左右。

归并排序的思想是将数组分成两部分,分别进行排序,然后归并起来。

归并方法将数组中两个已经排序的部分归并成一个。

将一个大数组分成两个小数组去求解。

因为每次都将问题对半分成两个子问题,这种对半分的算法复杂度一般为 O(NlogN)。

先归并那些微型数组,然后成对归并得到的微型数组。

取 a[l] 作为切分元素,然后从数组的左端向右扫描直到找到第一个大于等于它的元素,再从数组的右端向左扫描找到第一个小于它的元素,交换这两个元素。不断进行这个过程,就可以保证左指针 i 的左侧元素都不大于切分元素,右指针 j 的右侧元素都不小于切分元素。当两个指针相遇时,将切分元素 a[l] 和 a[j] 交换位置。

快速排序是原地排序,不需要辅助数组,但是递归调用需要辅助栈。

快速排序最好的情况下是每次都正好将数组对半分,这样递归调用次数才是最少的。这种情况下比较次数为 CN=2CN/2+N,复杂度为 O(NlogN)。

最坏的情况下,第一次从最小的元素切分,第二次从第二小的元素切分,如此这般。因此最坏的情况下需要比较 N2/2。为了防止数组最开始就是有序的,在进行快速排序时需要随机打乱数组。

因为快速排序在小数组中也会递归调用自己,对于小数组,插入排序比快速排序的性能更好,因此在小数组中可以切换到插入排序。

最好的情况下是每次都能取数组的中位数作为切分元素,但是计算中位数的代价很高。一种折中方法是取 3 个元素,并将大小居中的元素作为切分元素。

对于有大量重复元素的数组,可以将数组切分为三部分,分别对应小于、等于和大于切分元素。

三向切分快速排序对于有大量重复元素的随机数组可以在线性时间内完成排序。

快速排序的 partition() 方法,会返回一个整数 j 使得 a[l..j-1] 小于等于 a[j],且 a[j+1..h] 大于等于 a[j],此时 a[j] 就是数组的第 j 大元素。

可以利用这个特性找出数组的第 k 大的元素。

该算法是线性级别的,假设每次能将数组二分,那么比较的总次数为 (N+N/2+N/4+..),直到找到第 k 个元素,这个和显然小于 2N。

堆中某个节点的值总是大于等于其子节点的值,并且堆是一颗完全二叉树。

堆可以用数组来表示,这是因为堆是完全二叉树,而完全二叉树很容易就存储在数组中。位置 k 的节点的父节点位置为 k/2,而它的两个子节点的位置分别为 2k 和 2k+1。这里不使用数组索引为 0 的位置,是为了更清晰地描述节点的位置关系。

在堆中,当一个节点比父节点大,那么需要交换这个两个节点。交换后还可能比它新的父节点大,因此需要不断地进行比较和交换操作,把这种操作称为上浮。

类似地,当一个节点比子节点来得小,也需要不断地向下进行比较和交换操作,把这种操作称为下沉。一个节点如果有两个子节点,应当与两个子节点中最大那个节点进行交换。

将新元素放到数组末尾,然后上浮到合适的位置。

从数组顶端删除最大的元素,并将数组的最后一个元素放到顶端,并让这个元素下沉到合适的位置。

把最大元素和当前堆中数组的最后一个元素交换位置,并且不删除它,那么就可以得到一个从尾到头的递减序列,从正向来看就是一个递增序列,这就是堆排序。

一个堆的高度为logN,因此在堆中插入元素和删除最大元素的复杂度都为 logN。

对于堆排序,由于要对 N 个节点进行下沉操作,因此复杂度为 NlogN。

堆排序是一种原地排序,没有利用额外的空间。

现代操作系统很少使用堆排序,因为它无法利用局部性原理进行缓存,也就是数组元素很少和相邻的元素进行比较和交换。

计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,==计数排序要求输入的数据必须是有确定范围的整数==。

当输入的元素是 n 个 0 到 k 之间的整数时,它的==运行时间是 O(n + k)==。计数排序不是比较排序,排序的速度快于任何比较排序算法。由于用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),这使得计数排序对于数据范围很大的数组,需要大量时间和内存。比较适合用来排序==小范围非负整数数组的数组==。

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点:

同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。

当输入数据均匀分配到每一个桶时最快,当都分配到同一个桶时最慢。

实间复杂度N*K

快速排序是最快的通用排序算法,它的内循环的指令很少,而且它还能利用缓存,因为它总是顺序地访问数据。它的运行时间近似为 ~cNlogN,这里的 c 比其它线性对数级别的排序算法都要小。

使用三向切分快速排序,实际应用中可能出现的某些分布的输入能够达到线性级别,而其它排序算法仍然需要线性对数时间。

阅读全文

与c单链表排序算法相关的资料

热点内容
c语言编译器手机在线 浏览:848
战舰世界什么服务器地址 浏览:550
windowsphone解压缩 浏览:646
android工程目录结构 浏览:137
pdf文档是反的 浏览:528
javaobject比较 浏览:867
安卓如何设置微信屏幕锁 浏览:189
本溪云服务器 浏览:375
玩机技巧华为app如何了解纯净模式 浏览:905
换算法则数不变 浏览:719
java工作流activiti 浏览:788
单片机自动门程序 浏览:423
java培训长沙 浏览:494
程序员生存现状 浏览:588
光环游戏安装器在哪个文件夹 浏览:654
公众号图片被压缩 浏览:291
github优秀java 浏览:594
高压缩视频播放器 浏览:413
linux检测apache 浏览:741
运行命令ur 浏览:938