数据结构与算法分析学习笔记(1)--排序

来源:互联网 发布:吉他谱制作软件中文版 编辑:程序博客网 时间:2024/04/27 13:55

包括插入排序、希尔排序、堆排序、归并排序及快速排序

1、插入排序

插入排序利用了这样的事实:若插入位置为P,则位置0到位置P-1上的元素已排过序。每次插入前P+1个元素的正确位置。

void InsertionSort(ElementType a[], int N){ElementType tmp;int p, j;for (p = 1; p < N; p++){tmp = a[p];for (j = p; j>0 & a[j - 1] > tmp; j--)a[j] = a[j - 1];a[j] = tmp;}}


2、希尔排序

希尔排序是通过比较相距一段间隔的元素来工作,各趟比较所用的距离随着算法的进行而减少,直到只比较相邻元素的最后一趟排序为止。因此,有时也叫缩小增量排序(diminishing increment sort)。

void shellSort(ElementType a[], int N){ElementType tmp;int Increment, i, j;for (Increment = N / 2; Increment > 0; Increment /= 2){for (i = Increment; i < N; i++){tmp = a[i];for (j = i; j >= Increment; j -= Increment){if (a[j - Increment]>tmp)a[j] = a[j - Increment];elsebreak;}a[j] = tmp;}}}


不同增量序列:

(1)Hibbard增量:1,3,7,...,2^k-1

//****************希尔排序(Hibbard增量)****************//

int log2(int n){return int(log(double(n)) / log(double(2)));}void shellSort1(ElementType a[], int N){int Kt = log2(N);int k, Increment, i, j;ElementType tmp;for (k = Kt; k > 0; k--){Increment = int(pow(2.0, k) - 1);for (i = Increment; i < N; i++){tmp = a[i];for (j = i; j >= Increment; j -= Increment){if (a[j - Increment]>tmp)a[j] = a[j - Increment];elsebreak;}a[j] = tmp;}}}


(2)Sedgewick增量:9*4^i-9*2^i+1

//*****************希尔排序(Sedgewick增量)***************//

int log4(int n){return int(log(double(n)) / log(double(4)));}void shellSort2(ElementType a[], int N){int Kt = log4((N-1)/9);int k, Increment, i, j;ElementType tmp;for (k = Kt; k >=0; k--){Increment = int(9*pow(4.0, k)-9*pow(2.0,k) + 1);for (i = Increment; i < N; i++){tmp = a[i];for (j = i; j >= Increment; j -= Increment){if (a[j - Increment]>tmp)a[j] = a[j - Increment];elsebreak;}a[j] = tmp;}}}


3、堆排序

最大堆的父节点大于等于任意一个孩子节点,所以每次可以取出根节点进行排序,为了不使用附加的数组,可以将根节点与最后一个元素交换,然后下滤来保持堆性质,依次类推,最后得到一个从小到大的序列。

#define LeftChild(i) (2*(i)+1)//数组是从0开始的//***************堆排序********************************//void PercDown(ElementType a[], int i, int N){int child;ElementType tmp;for (tmp = a[i]; LeftChild(i) < N; i = child){child = LeftChild(i);if (child != N - 1&&a[child+1]>a[child])child++;if (tmp < a[child])a[i] = a[child];elsebreak;}a[i] = tmp;}void Heapsort(ElementType a[], int N){int i;for (i = N / 2; i >= 0; i--)PercDown(a, i, N);for (i = N - 1; i > 0; i--){swap(a[0], a[i]);PercDown(a, 0, i);}}


4、归并排序

对两个已经排好序的子序列排序。

void Merge(ElementType a[], ElementType TmpArray[], int Lpos, int Rpos, int RightEnd){int i, LeftEnd, TmpPos, NumElements;LeftEnd = Rpos - 1;TmpPos = Lpos;NumElements = RightEnd - Lpos + 1;while (Lpos <= LeftEnd&&Rpos <= RightEnd){if (a[Lpos] <= a[Rpos])TmpArray[TmpPos++] = a[Lpos++];elseTmpArray[TmpPos++] = a[Rpos++];}while (Lpos <= LeftEnd)TmpArray[TmpPos++] = a[Lpos++];while (Rpos <= RightEnd)TmpArray[TmpPos++] = a[Rpos++];for (i = 0; i < NumElements; i++, RightEnd--){a[RightEnd] = TmpArray[RightEnd];}}void MSort(ElementType a[], ElementType TmpArray[], int left, int right){int center;if (left < right){center = (left + right) / 2;MSort(a, TmpArray, left, center);MSort(a, TmpArray, center + 1, right);Merge(a, TmpArray, left, center + 1, right);}}void Mergesort(ElementType a[], int N){ElementType *TmpArray;TmpArray =(ElementType *)malloc(N*sizeof(ElementType));if (TmpArray != NULL){MSort(a, TmpArray, 0, N - 1);free(TmpArray);//free出错,可能是数组越界}elseprintf("No space for array!!!");}


5、快速排序

快速排序与归并排序一样也是一种递归的分治方法,选取一个pivot,将小于或等于pivot的放在左边,将大于或等于pivot的放在右边。

//******************快速排序*********************************//ElementType Median3(ElementType a[], int left, int right){int center = (left + right) / 2;if (a[left] > a[center])swap(a[left], a[center]);if (a[left] > a[right])swap(a[left], a[right]);if (a[center] > a[right])swap(a[center], a[right]);swap(a[center], a[right - 1]);return a[right - 1];}void Qsort(ElementType a[], int left,int right){int i, j;ElementType pivot;if (left + cutoff <= right){pivot = Median3(a, left, right);i = left;j = right - 1;for (;;){while (a[++i] < pivot){}while (a[--j]>pivot){}if (i < j)swap(a[i], a[j]);elsebreak;}swap(a[i], a[right - 1]);Qsort(a, left, i - 1);Qsort(a, i + 1, right);}else{InsertionSort(a + left, right - left + 1);}}void QuickSirt(ElementType a[], int N){Qsort(a, 0, N - 1);}


快速查找**************************************// void Qselect(ElementType a[], int k, int left, int right){int i, j;ElementType pivot;if (left + cutoff <= right){pivot = Median3(a, left, right);i = left;j = right - 1;for (;;){while (a[++i] < pivot){}while (a[--j]>pivot){}if (i < j)swap(a[i], a[j]);elsebreak;}swap(a[i], a[right - 1]);if (k <= i)Qselect(a, k, left, i - 1);else if (k>i + 1)Qselect(a, k, i + 1, right);}else{InsertionSort(a + left, right - left + 1);}} ElementType QuickSelect(ElementType a[], int k,int N) {Qselect(a, k, 0, N - 1);return a[k - 1]; }


用到的其他函数及主函数

#include "stdafx.h"#include<time.h>#include<math.h>#include<stdlib.h>#include<malloc.h>#define M 10#define LeftChild(i) (2*(i)+1)#define cutoff 3typedef int ElementType;void randm(int a[])  //产生随机数{int i;int b;srand(time(NULL));for (i = 0; i < M; i++){b = rand();a[i] =  (b% 100);}}void swap(ElementType &a, ElementType &b)//交换两个数{ElementType tmp;tmp = a;a = b;b = tmp;}int _tmain(int argc, _TCHAR* argv[]){int a[M] = { 21,71,71,26,93,95,35,78,84,47 };//randm(a);for (int i = 0; i < M; i++)printf("%d ", a[i]);printf("\n");QuickSirt(a, M);for (int i = 0; i < M; i++)printf("%d ", a[i]);ElementType p;p=QuickSelect(a, 5,10);printf("\n%d\n", p);return 0;}


0 0
原创粉丝点击