Bill retired
07.04.2008 by drivel - 0 CommentPosted in DotNet, M$ & Window$
Bill is good businessman,but Windows is a crap product.
CSharp is a good programing language,but .Net project sucks.
Bill is good businessman,but Windows is a crap product.
CSharp is a good programing language,but .Net project sucks.
一个可行的办法使用System.Diagnostics.Process列举出所有的运行的进程,然后System.Diagnostics.ProcessThreadCollection 来得到他们的.Threads属性,为了得到thread Id,我们使用Win32 API EnumThreadWindows(DWORD threadId,WNDENUMPROC lpfn,LPARAM lParam) 来实现,这是一个回调(call back)函数,他可以列举出于进程相关的窗体。当我们得到了窗体的句柄以后,我们可以使用另一个API函数 GetWindowText(HWND hwnd,/*out*/LPTSTR lpString,int nMaxCount)来得到窗体的标题,然后根据已经有的窗体,调用API函数SendMessage(HWND hWnd,int msg,int wParam,int lParam)来关闭窗口。下面是演示代码
交换排序的基本思想是:两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。
应用交换排序基本思想的主要排序方法有:冒泡排序和快速排序。
冒泡排序
Cmin=n-1
Mmin=0。
冒泡排序最好的时间复杂度为O(n)。
Cmax=n(n-1)/2=O(n2)
Mmax=3n(n-1)/2=O(n2)
冒泡排序的最坏时间复杂度为O(n^2)。
①冒泡排序的不对称性
能一趟扫描完成排序的情况:
只有最轻的气泡位于R[n]的位置,其余的气泡均已排好序,那么也只需一趟扫描就可以完成排序。
【例】对初始关键字序列12,18,42,44,45,67,94,10就仅需一趟扫描。
需要n-1趟扫描完成排序情况:
当只有最重的气泡位于R[1]的位置,其余的气泡均已排好序时,则仍需做n-1趟扫描才能完成排序。
【例】对初始关键字序列:94,10,12,18,42,44,45,67就需七趟扫描。
②造成不对称性的原因
每趟扫描仅能使最重气泡”下沉”一个位置,因此使位于顶端的最重气泡下沉到底部时,需做n-1趟扫描。
③改进不对称性的方法
在排序过程中交替改变扫描方向,可改进不对称性。具体算法。
快速排序(QuickSort)
注意:
划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]):
R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
其中low≤pivotpos≤high。
注意:
为排序整个文件,只须调用QuickSort(R,1,n)即可完成对R[l..n]的排序。
① 具体做法
第一步:(初始化)设置两个指针i和j,它们的初值分别为区间的下界和上界,即i=low,i=high;选取无序区的第一个记录R[i](即R[low])作为基准记录,并将它保存在变量pivot中;
第二步:令j自high起向左扫描,直到找到第1个关键字小于pivot.key的记录R[j],将R[j])移至i所指的位置上,这相当于R[j]和基准R[i](即pivot)进行了交换,使关键字小于基准关键字pivot.key的记录移到了基准的左边,交换后R[j]中相当于是pivot;然后,令i指针自i+1位置开始向右扫描,直至找到第1个关键字大于pivot.key的记录R[i],将R[i]移到i所指的位置上,这相当于交换了R[i]和基准R[j],使关键字大于基准关键字的记录移到了基准的右边,交换后R[i]中又相当于存放了pivot;接着令指针j自位置j-1开始向左扫描,如此交替改变扫描方向,从两端各自往中间靠拢,直至i=j时,i便是基准pivot最终的位置,将pivot放在此位置上就完成了一次划分。
②一次划分过程
一次划分过程中,具体变化情况【参见动画演示】
③划分算法:
(2) 递归树上每一结点左旁方括号表示当前待排序的区间,结点内的关键字是划分的基准关键字
注意:
叶结点对应的子区间只有一个关键字,无须划分,故叶结点内没有基准关键字
(3) 划分后得到的左、右两个子区间分别标在该结点的左、右两个孩子结点的左边方括号内。
【例】根结点左旁方括号[49,38,65,97,76,13,27,49]表示初始待排序的关键字,根内的49表示所选的划分基准记录的关键字,划分结果是[27,28,13]49[76,97,65,49_],其左右子区间分别标在根结点的两个孩子的左边。
(4) 每个分支结点右旁圆括号中的内容表示对该结点左旁区间的排序过程结束之后返回的结果。它是其左右孩子对应的区间排序完成之后,将左右孩子对应的排序结果分别放在该分支结点的关键字前后所得到的关键字序列。
【例】分支结点76的左右孩子对应的区间排序后的结果分别是(49_,65)和(97),将它们分别放在76的前后即得(49,65,76,97),这是对结点76左旁区间[76,97,,65,49]排序的结果。
(5) 算法的执行顺序是递归树中的箭头顺序,实际上当把划分操作视为访问结点的操作时,快速排序的执行过程相当于是先序遍历其递归树。
[27 38 13] 49 [76 97 65 49] //第1次划分完成之后,对应递归树第2层
[13] 27 [38] 49 [49 65] 76 [97] //对上一层各无序区划分完成后,对应递归树第3层
13 27 38 49 49 [65] 76 97 //对上一层各无序区划分完成后,对应递归树第4层
13 27 38 49 49 65 76 97 //最后的排序结果
(1)最坏时间复杂度
②取位于low和high之间的随机数k(low≤k≤high),用R[k]作为基准
选取基准最好的方法是用一个随机函数产生一个取位于low和high之间的随机数k(low≤k≤high),用R[k]作为基准,这相当于强迫R[low..high]中的记录是随机分布的。用此方法所得到的快速排序一般称为随机的快速排序。具体算法【参见教材】
注意:
随机化的快速排序与一般的快速排序算法差别很小。但随机化后,算法的性能大大地提高了,尤其是对初始有序的文件,一般不可能导致最坏情况的发生。算法的随机化不仅仅适用于快速排序,也适用于其它需要数据随机分布的算法。