Bubble sort{src 1} aims at sending lesser elements to the right. It is an in-place sort, and steps through each element in the array. Comparisons are done with immediate successors, starting from the first element. If the successor is bigger, the two elements swap places. [function bubble0() in the source shown]. After the first iteration, the element rightmost in the array is the least. So the array has n-i unsorted elements (array[0] to array[n-i-1]), after i iterations. Which means we need n iterations to finish sorting, in each of which we do not consider the last i items, ie consider only the first n-i items.
{Src 1} also shows insertion sort. Here we work like we have a hand of cards. You can see only one card initially, which is the first card in your hand. Then you look at the cards underneath (one by one). If it is bigger than the card above it, then move it one place upward. The upward motion continues until there is a bigger card in front, or we have come to the top of our hand. Unlike bubblesort, you do not know the final position of any card until you have looked at the last card of your hand.
A heap is a binary tree data structure. Nodes of the binary tree are so arranged that, if a node has two child nodes, the parent node's data value is greater than either of its children's data. In that way, parent can have data '5' with one child '3' and the other '1'. The binary tree structure can be represented as an array, with nodes indexed level-by-level from left to right. The root node would take index 0, its left child 1, and its right child 2. 1's children will have indices 3 and 4, and 2's children 5 and 6. Using a node's index, we can find the left child's index as 2 * (i +1) -1, the right child index as 2 * (i +1), and the parent as (i-1)/2.
With this idea, we can consider our input array as a binary tree structure. Enforcing the heap property requires that the root node have the highest data value in the tree. The leaf nodes do not have any children, and hence the heap property [function heapify() in src 2] does not apply to them. So the algorithm considers all non-leaf nodes (interior nodes), and checks if the heap property wrt that node is ok. If not, it means that one of the children have greater data value. So the biggest child swaps places with the parent, and the parent's new location is scrutinized again in a recursive call. After we have looked into all non-leaf nodes, the root becomes the biggest node, and the last element in the array, one of the least.