Code of sorting algorithm - insertion sort

Table of contents

Did not test the code.

Problems when writing code:

insertion sort

Direct insertion sort with sentinels

Direct insertion sort without sentinels

Binary insertion sort (binary insertion sort)

Hill sort


Did not test the code.

Problems when writing code:

1. I don’t know how to name the nouns of each sorting algorithm.

It is recommended to use: Insortsert. Direct insertion search: Insortsert, binary search (binary search): Binarysearch (Binary: binary)

2. I don’t know what is the formal parameter in the sorting algorithm? Direct insertion sort is the array name and length:

        functionName(ElemType a[], int n);

        The half insertion sort is (Selist L, Elwmtype key );

3. Direct insertion sorting does not work, and does not know where to insert.

4. When is j in direct insertion sorting, and when is j+1 used.

5. In Hill sorting, what is dk equal to? Is it rounded down? ? ?

Why can't I see that it is A[1], A[4], A[7],? ? ? How is the step from A[4] to A[7] done?

insertion sort

Direct insertion sort with sentinels

Idea: It is required that the sequence from beginning to end is from small to large. If it is found that the last number in the sequence is smaller than the previous one, it does not meet the requirements, such as A > B; give the value of B to the sentinel, and then overwrite B with A, that is, A[i+1]=A[i ]. Then assign the sentinel value to the position of A (A[i]). A switch between A and B is realized. Sentinels are equivalent to temp.

However, unlike exchanging data, direct insertion sorting is not just the exchange of two adjacent elements, but if the element to be sorted is smaller than the maximum value of the sequence elements that have been sorted, it must be in the sequence that has been sorted Find the corresponding position and empty the position (backward move operation).

//直接插入排序·带哨兵,A[0]是哨兵的位置,从A[1开始存放排序的序列。
void InsertSort(int A[], int n){
	int i,j;

    //将各元素插入已经排好序的序列中,A[2]~A[n]插入到前面已排列序列
	for ( i = 2; i <= n; i++)//这里居然有等于号?
	{
		if (A[i] < A[i-1])
		{
			//若A[i] 关键字小于前驱
			A[0] = A[i];//哨兵更新为每次即将排序的元素的值。
			for ( j = i-1;A[0] < A[j]; --j)
			{
				//从后往前查找待插入位置
				A[j+1] = A[j];//向后挪位
			}
			A[j+1] = A[0];//复制到插入位置
		}	
	}	
}

Direct insertion sort without sentinels

//直接插入排序·不带哨兵
void InsertSort(int A[], int n){
	int i,j,temp;

	//将各元素插入已经排好序的序列中,
	for ( i = 1; i < n; i++)
	{
		if (A[i] < A[i-1])
		{
			//若A[i] 关键字小于前驱
			temp = A[i];//用temp暂存A[i]
			for ( j = i-1;j >= 0 && A[j] > temp; --j)
			{
				A[j + 1] =A[j];
			}
            A[j+1] = temp;
		}	
	}	
}

Binary insertion sort (binary insertion sort)

Use the half search to find the position to be inserted, and then move all the elements after the position to be inserted backwards to insert the element.


//在顺序表上折半查找的实现
typedef	struct{
	//查找表的数据结构:顺序表
	ElemType *elem;	//动态数组基址
	int TableLen;	//表的长度
}SSTable;

int Binary_Search(SeList L, ElemType key)
{
	int low = 0, high = L.Tablelen - 1, mid;
	while (low <= high)
	{
		mid = (low + high) /2;
		if (L.elem[mid] == key)
		{
			return mid;
		}
		 else if (L.elem[mid] > key)
		{
			high = mid - 1;
		}
		else 
			low = mid + 1;
	}
	return -1;
}
//折半插入排序。是在已经排好序的序列里查找该插入的位置。所以high = i-1.
void  Insertsort(ElemType a[],int n){
	int i,j,mid,low,high;
	for ( i = 2; i <= n; i++)
	{
		//目的:依次将a[2]-a[n]插入到前面的已排好序列。
		a[0]=a[i];//将a[i] 暂存到a[0]
		low = 1,high = i-1;
		while (low <= high)
		{
			mid =(low + high) /2;
			if (a[mid] > a[0])
			{
				high = mid - 1;
			}
			else 
			{
				low = mid + 1;
				//但如果是要插入6,mid =5,mid+1=8怎么办? 
			}	
		}
		//后移,插入操作。注意,经过折半查找后的high等于将要插入的位置-1。
		//因为high =mid -1.最后之后,
		for (j = i -1; j >= high+1 ; j--)
		{
			a[j+1] =a[j];
		}
		a[high+1] = a[0];//因为到达j= high+1
	}
}

Hill sort

//使用希尔排序进行升序排列
#include <stdio.h>

void ShellInsert(int A[], int n);

int main() 
{
	int A[20],n;
	printf("请输入要输入的元素个数:\n");
	scanf("%d",&n);
	printf("请输入要排序的序列:\n");
	for (int i=1; i<=n; i++){
        //输入的元素从1开始,0做哨兵
        scanf("%d",&A[i]);
    } 	
	ShellInsert(A,n);
	for(int i=1; i<=n; i++)
    {
        printf("%d  ",A[i]);
    }	
	printf("\n");

	return 0;
}

void ShellInsert(int A[], int n)
{
    //A[0]只是暂存单元,不是哨兵。因为后面j可以<0,也就是越过a[0]. 当j <= 0时,插入位置已到
    //数值是从A[1]开始存储的。下标不是从0开始的。
	int dk,i,j;
	for(dk=n/2; dk>=1; dk=dk/2) 
    {
		for(i=dk+1; i<=n; i++) 
        {
			if(A[i]<A[i-dk]) 
            {
                //需将A[i]插入有序增量子表
				A[0]=A[i];//暂存在A[0]
				for(j=i-dk; j>0 && A[0]<A[j]; j -= dk)
                {
					A[j+dk]=A[j];//记录后移,查找插入的位置。
				}
				A[j+dk]=A[0];
			}
		}
	}
}

In the above algorithm, I think the most difficult part is the innermost for loop. In the front, a[i] and a[i-dk] were compared, and then exchanged in the next for loop which is the innermost layer. So j=i-dk, then a[j+dk] =a[j], is to assign the value of a[j] to a[i].

Next, in the for loop, after the exchange is completed, execute j= j-dk; if it is the first round, then j-dk must be <0. If it is the second round or the third round, the loop will continue, and then the size of a[0] and the new a[j] will be judged, whether they are exchanged, and the result of the last step is also j<0.

The next j+dk will bring j to the original i-dk. Then give the value of a[i] to a[j]. Complete the exchange.

But there is something I don't understand, dk=dk/2, 5/2 is equal to 2? In the example dk=3. ? ? ? ?

Guess you like

Origin blog.csdn.net/weixin_48060069/article/details/126910636