/********************************************************************
* File Name : quick_sort.c *
* Created : 2007/05/08 *
* Author : SunYonggao *
* Description : 對雙向鏈表進行快速排序
*********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//定義類型 所有的排序例子中都是用的int作為data
typedef int elemType;
//傳回值
#define RET_SUCCESS ( 1 )
#define RET_FAILED ( 0 )
//定義鏈表的長度
#define LIST_MAX_SIZE (10)
//定義鏈表申請記憶體不夠時報錯資訊
#define NO_MEMORY printf("Error! Not enough memory!/n");exit(1)
//雙向鏈表結構體定義
typedef struct tagDuNode_t
{
elemType data;
struct tagDuNode_t * pstNext;
struct tagDuNode_t * pstPrior;
}duNode_t;
//初始化雙向鏈表
int initDuList(duNode_t ** pstHead)
{
int iRet = RET_SUCCESS;
int iCir = 0;
duNode_t * pstTmp1 = NULL;
duNode_t * pstTmp2 = NULL;
//初始化前端節點
* pstHead = (duNode_t *)malloc(sizeof(duNode_t));
(* pstHead)->pstPrior = NULL;
(* pstHead)->pstNext = NULL;
if ( !pstHead )
{
NO_MEMORY;
}
pstTmp1 = * pstHead;
//鏈表初始化
srand( time(NULL) );//隨機數
for( iCir = 0; iCir < LIST_MAX_SIZE; iCir++ )
{
pstTmp2 = (duNode_t *)malloc(sizeof(duNode_t));
if ( !pstTmp2 )
{
NO_MEMORY;
}
//賦初值
pstTmp2->data = rand() % LIST_MAX_SIZE;
pstTmp2->pstNext = NULL;
pstTmp1->pstNext = pstTmp2;
pstTmp2->pstPrior = pstTmp1;
pstTmp1 = pstTmp2;
}
return iRet;
}
// 列印鏈表 鏈表的data元素是可列印的整形
int showDuList(duNode_t * pstHead)
{
int iRet = RET_SUCCESS;
duNode_t * pstTmp = pstHead->pstNext;
if ( NULL == pstHead )
{
printf("鏈表的前端節點是空/n");
iRet = RET_FAILED;
}
else
{
while ( pstTmp )
{
printf("%d ", pstTmp->data);
pstTmp = pstTmp->pstNext;
}
printf("/n");
}
return iRet;
}
/* 刪除包括前端節點在內的所有的節點. 07/04/28 */
int destroyList(duNode_t * pstHead)
{
duNode_t * pstTmp = NULL; /* Temp pointer for circle */
int iRet = RET_SUCCESS;
if ( !pstHead )
{
printf("Error! pstHead is null/n");
iRet = RET_FAILED;
}
else
{
while ( pstHead ) /* Free nodes */
{
pstTmp = pstHead;
pstHead = pstHead->pstNext;
free(pstTmp);
}
pstHead = NULL;
}
return iRet;
}/* End of destroyList----------------------------------------------*/
//正確的快速排序 2007/05/09
/*
一趟快速排序的具體做法是:附設兩個指標low和high(即第一個和最後一個指標),
他們的初值分別為low和high設樞軸(一般為low的值pivot)記錄的關鍵字
(即本例子中的整形data)為pivot,則首先從high所指位置
起向前搜尋到第一個關鍵字小於pivot的記錄和樞軸記錄交換,然後從low所指位置起
向後搜尋,找到第一個關鍵字大於pivot的記錄和樞軸記錄相互交換,重複這兩步直
至low = high為止。
*/
duNode_t * partion(duNode_t * pstHead, duNode_t * pstLow, duNode_t * pstHigh)
{
elemType iTmp = 0;
elemType pivot = 0;
if ( !pstHead )
{
printf("錯誤,前端節點為空白!/n");
exit(1);
}
if ( !pstHead->pstNext )
{
return pstHead->pstNext;//就一個元素
}
pivot = pstLow->data;
while ( pstLow != pstHigh )
{
//從後面往前換
while ( pstLow != pstHigh && pstHigh->data >= pivot )
{
pstHigh = pstHigh->pstPrior;
}
//交換high low
iTmp = pstLow->data;
pstLow->data = pstHigh->data;
pstHigh->data = iTmp;
//從前往後換
while ( pstLow != pstHigh && pstLow->data <= pivot )
{
pstLow = pstLow->pstNext;
}
//交換high low
iTmp = pstLow->data;
pstLow->data = pstHigh->data;
pstHigh->data = iTmp;
}
return pstLow;
}
//快排
void quick_sort(duNode_t * pstHead, duNode_t * pstLow, duNode_t * pstHigh)
{
duNode_t * pstTmp = NULL;
pstTmp = partion(pstHead, pstLow, pstHigh);
if ( pstLow != pstTmp )
{
quick_sort(pstHead, pstLow, pstTmp->pstPrior);
}
if ( pstHigh != pstTmp )
{
quick_sort(pstHead, pstTmp->pstNext, pstHigh);
}
}
void main()
{
duNode_t * pstHead = NULL;
duNode_t * pstHigh = NULL;
duNode_t * pstTmp = NULL;
initDuList(&pstHead); //初始化
printf("Before sorting:/n");
showDuList(pstHead); //列印
pstTmp = pstHead->pstNext;
while ( pstTmp->pstNext )
{
pstTmp = pstTmp->pstNext;
}
pstHigh = pstTmp;//找到最後一個節點的指標用於快排時
quick_sort(pstHead, pstHead->pstNext, pstHigh);//快排序
printf("After sorting:/n");
showDuList(pstHead);
destroyList(pstHead);
pstHead = NULL;
}
/* End of file ----------------------------------------------------*/