
输入代码,编译运行程序。
三、 程序代码
sequence.cpp : Defines the entry point for the console application.
主要用到的WINAPI线程控制函数,有关详细表明请查看MSDN;
线程建立变量:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,// 安全属性结构指针,可为NULL;
DWORD dwStackSize,// 线程栈大小,若为0表示使用默认值;
LPTHREAD_START_ROUTINE lpStartAddress,// 指向线程函数的指针;
LPVOID lpParameter,// 传递给线程函数的参数,可以保存一个指针值;
DWORD dwCreationFlags,// 线程构建是的初始标记,运行或挂起;
LPDWORD lpThreadId// 指向接收线程号的DWORD变量;
);
对临界资源控制的多线程控制的信号函数:
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,// 安全属性结构指针ccriticalsection 调用 2次,可为NULL;
BOOLbManualReset,// 手动清除信号标记,TRUE在WaitForSingleObject后需要自动//调用RetEvent清除信号。若为FALSE则在WaitForSingleObject
//后,系统自动消除事件信号;
BOOLbInitialState,// 初始状况,TRUE有信号,FALSE无信号;
LPCTSTR lpName// 信号量的名称,字符数不可多于MAX_PATH;
//如果遇到同名的其它信号量函数经常失败,如果遇
//到同类信号同名也应留意变化;
);
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,// 安全属性结构指针,可为NULL
BOOLbInitialOwner,// 当前建立互斥量是否占有该互斥量TRUE表示占有,
//这样其它线程就不能获得此互斥量也就能够开启由
//该互斥量控制的临界区。FALSE表示不占有该互斥量
LPCTSTR lpName// 信号量的名称,字符数不可多于MAX_PATH如果
//遇到同名的其它信号量函数就会失败,
//如果遭遇同类信号同名也应留意变化;
);
//初始化临界区信号,使用前需要先初始化
VOIDInitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection// 临界区变量指针
);
//阻塞函数
//如果等待的信号量不可用,那么线程都会挂起,直到信号可用
//线程能够被激活,该变量会手动设置信号,如Event,线程被唤醒之后
//Event信号会更加无信号,Mutex、Semaphore等也会变。
DWORD WaitForSingleObject(
HANDLE hHandle,// 等待对象的句柄
DWORD dwMilliseconds// 等待毫秒数,INFINITE表示无限等待
);
//如果应等待多个信号可以使用WaitForMutipleObject函数
#include "stdafx.h"
#include "stdlib.h"
#include "memory.h"
HANDLE evtTerminate;//事件信号,标记是否所有子线程都执行完
/*
下面使用了三种控制方式,你可以注释其中两种,使用其中一种。
注意设置时应连带修改临界区PrintResult里的相应控制语句
*/
HANDLE evtPrint;//事件信号,标记事件是否未出现
//CRITICAL_SECTION csPrint; //临界区

//HANDLE mtxPrint; //互斥信号,如有信号表明即将有线程处于临界区并拥有此信号
staticlongThreadCompleted= 0;
/*用来标记四个子线程中未完成线程的个数,当一个子线程完成时就对ThreadCompleted进行加一操作, 要使用InterlockedIncrement(long* lpAddend)和InterlockedDecrement(long* lpAddend)进行加减操作*/
//下面的结构是用于传送排序的数据帮各个顺序子线程
structMySafeArray
{
long* data;
intiLength;
};
//打印每一个程序结果
voidPrintResult(long* Array,intiLength,constchar* HeadStr= "sort");
//排序函数
unsignedlong__stdcall BubbleSort(void* theArray);//冒泡排序
unsignedlong__stdcall SelectSort(void* theArray);//选择排序
unsignedlong__stdcall HeapSort(void* theArray);//堆排序
unsignedlong__stdcall InsertSort(void* theArray);//插入排序
以上四个函数的声明需要合适作为一个线程函数的必要条件才可以使用CreateThread建立一个线程。
调用方式需要是__stdcall,即变量参数压栈顺序由右到左,而且由函数原本负责
栈的恢复, C跟C++默认是__cdecl, 所以要显式声明是__stdcall
返回值必须是unsigned long
参数需要是一个32位值,如一个指针值或long类型
如果函数是类成员变量,必须声明为static函数,在CreateThread时变量指针有特殊的写法。如下(函数是类CThreadTest的成员函数中):
staticunsignedlong_stdcall MyThreadFun(void* pParam);
handleRet= CreateThread(NULL,0,&CThreadTestDlg::MyThreadFun,NULL,0,&ThreadID);
之所以要声明为static是因为,该变量应该应独立于对象示例来使用,即使没有声明范例也可以使用。
int QuickSort(long* Array,intiLow,intiHigh);//快速排序
intmain(intargc,char* argv[])
{
longdata[]= {123,34,546,754,34,74,3,56};
intiDataLen= 8;
//为了对各个子线程分别对原始数据进行顺序和保存排序结果
//分别分配存储对data数组的数据进行复制
long*data1,*data2,*data3,*data4,*data5;
MySafeArray StructData1,StructData2,StructData3,StructData4;
data1= newlong[iDataLen];
memcpy(data1,data,iDataLen<< 2);//把data中的数据复制到data1中
//内存复制 memcpy(目标存储指针, 源硬盘指针, 复制字节数), 因为long的长度
//为4字节,所以复制的字节数为iDataLen << 2, 即等于iDataLen*4
StructData1.data= data1;
StructData1.iLength= iDataLen;
data2= newlong[iDataLen];
memcpy(data2,data,iDataLen<< 2);
StructData2.data= data2;
StructData2.iLength= iDataLen;
data3= newlong[iDataLen];
memcpy(data3,data,iDataLen<< 2);
StructData3.data= data3;
StructData3.iLength= iDataLen;
data4= newlong[iDataLen];
memcpy(data4,data,iDataLen<< 2);
StructData4.data= data4;
StructData4.iLength= iDataLen;
data5= newlong[iDataLen];
memcpy(data5,data,iDataLen<< 2);
unsignedlongTID1,TID2,TID3,TID4;

//对信号量进行初始化
evtTerminate= CreateEvent(NULL,FALSE,FALSE,"Terminate");
evtPrint= CreateEvent(NULL,FALSE,TRUE,"PrintResult");
//分别建立各个子线程
CreateThread(NULL,0,&BubbleSort,&StructData1,NULL,&TID1);
CreateThread(NULL,0,&SelectSort,&StructData2,NULL,&TID2);
CreateThread(NULL,0,&HeapSort,&StructData3,NULL,&TID3);
CreateThread(NULL,0,&InsertSort,&StructData4,NULL,&TID4);
//在主线程中执行行快速排序,其他次序在子线程中执行
QuickSort(data5,0,iDataLen- 1);
PrintResult(data5,iDataLen,"Quick Sort");
WaitForSingleObject(evtTerminate,INFINITE);//等待所有的子线程结束
//所有的子线程结束后,主线程才可以结束
delete[]data1;
delete[]data2;
delete[]data3;
delete[]data4;
CloseHandle(evtPrint);
return0;
}
冒泡排序思想(升序,降序同理,后面的算法一样都是升序):从头到尾对数据进行两两比较进行交换,小的放前大的放后。这样一次出来,最大的元素都会被交换的最终,然后下一次循环就不用对最后一个元素进行非常交换了,所以呢每一次比较交换的数量都比上一次循环的数量少一,这样N次之后数据就显得升序排列了。
unsignedlong__stdcall BubbleSort(void* theArray)
{
long* Array= ((MySafeArray*)theArray)->data;
intiLength= ((MySafeArray*)theArray)->iLength;
inti,j=0;
longswap;
for(i= iLength-1;i>0;i--)
{
for(j= 0;j< i;j++)
{
if(Array[j]>Array[j+1])//前比后大,交换
{
swap= Array[j];
Array[j]= Array[j+1];
Array[j+1]= swap;
}
}
}
PrintResult(Array,iLength,"Bubble Sort");//向控制台打印排序结果
InterlockedIncrement(&ThreadCompleted);//返回前让线程完成数标记加1
if(ThreadCompleted== 4)SetEvent(evtTerminate);//检查能否其他线程都未执行完
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-143108-1.html
我觉得好
没办法
日本军事储存能力比你想象强得多