堆、歸併排序

數據結構中的堆,是一顆完全二叉樹,以連續地址存儲。插入的方式是,先將元素放到vector尾部,然後vector不斷和父母節點比較交換,直到找到合適的位置,所以時間複雜度是O(lgN),也就是樹的高度。刪除第一個元素的方式是,先將最後的元素跟第一個元素交換,然後將最後的元素刪除,然後第一個元素再跟兩個孩子節點中的一個交換,直到找到合適的位置,所以時間複雜度也是O(lgN)。

其中堆排序就是每次調整都是從父結點、左孩子結點、右孩子結點三者中選擇最大者跟父結點進行交換(交換之後可能造成被交換的孩子結點不滿足堆的性質,因此每次交換之後要重新對被交換的孩子節點進行調整)。有了初始堆之後就可以進行排序了。

根結點(亦稱爲堆頂)的關鍵字是堆裏所有結點關鍵字中最小者的堆稱爲小根堆。 
根結點(亦稱爲堆頂)的關鍵字是堆裏所有結點關鍵字中最大者,稱爲大根堆


//堆排序
void HeapAdjust(int*a,int i,int size)
{
 int lchild = 2*i;
 int rchild = 2*i+1;
    int max = i;
 if (i<=size/2)
 {
  if (lchild<=size&&a[lchild]>a[max])
  {
   max= lchild;
  }
  if (rchild<=size&&a[rchild>a[max])
  {
   max = rchild;
  }
  if (max!=i)
  {
   swap(a[i],a[max]);
   HeapAdjust(a,max,size);
  }
 }
}
void buidheap(int *a,int size)
{
 for (int i=size/2;i>0;i--)
 {
  HeapAdjust(a,i,size);
 }
}
void HeapSort(int*a,int size)
{
 if (a==NULL&&size<2)
 {
  return;
 }
 buidheap(a,size);
 for (int i=size;i>0;i--)
 {
  swap(a[1],a[i]);
  HeapAdjust(a,1,i-1);
 }

}



//歸併排序的實現代碼:
//將有二個有序數列a[first...mid]和a[mid...last]合併。  
void mergearray(int a[], int first, int mid, int last, int temp[])
{
    int i = first, j = mid + 1;
    int m = mid, n = last;
    int k = 0;

    while (i <= m && j <= n)
    {
        if (a[i] <= a[j])
            temp[k++] = a[i++];
        else
            temp[k++] = a[j++];
    }

    while (i <= m)
        temp[k++] = a[i++];

    while (j <= n)
        temp[k++] = a[j++];

    for (i = 0; i < k; i++)
        a[first + i] = temp[i];
}
void mergesort(int a[], int first, int last, int temp[])
{
    if (first < last)
    {
        int mid = (first + last) / 2;
        mergesort(a, first, mid, temp);    //左邊有序  
        mergesort(a, mid + 1, last, temp); //右邊有序  
        mergearray(a, first, mid, last, temp); //再將二個有序數列合併  
    }
}

bool MergeSort(int a[], int n)
{
    int *p = new int[n];
    if (p == NULL)
        return false;
    mergesort(a, 0, n - 1, p);
    delete[] p;
    return true;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章