Review the old and know the new - > data structure - > sorting - > program implementation 1_ Using C language

Posted by Karlos2394 on Wed, 02 Feb 2022 03:59:01 +0100

Review the old and know the new - > data structure - > sorting - > program implementation 1_ Using C language

This blog is based on Review the old and know the new - > data structure - > sorting Part of the theoretical knowledge of sorting in the program!

Among them, three kinds of quick sorting in exchange sorting, recursive and non recursive merge sorting, non comparison sorting and so on are realized! With relevant examples and corresponding running results!

Because the sequence table and queue are used in the above program implementation, that is, the sequence table and queue need to be implemented, which will lead to a significant increase in the amount of program code. In the program, in order to clearly show the implementation code of each part, there are five files, namely queue h ,seqList.h ,queue.c ,seqList.c and main c .

Where queue H and queue C. contents and Review the old and know the new - > data structure - > queue - > program implementation 1_ Using structure Newqueue in blog H and main The above program is the same as that of C Delete or comment the test() and main() functions in C;
And seqlist H and seqlist C. contents and Review the old and know the new - > data structure - > sequence table - > program implementation 1_ Using structure Seqlist in blog H and main C corresponds to and is the same. In order to facilitate the operation of this program, it is necessary to put the main of the above blog The test() and main() functions in C are deleted or commented.

The main of this procedure will be attached in the following contents C. document contents. Other document contents can be viewed by yourself according to the above guidelines!

Note: the following code is more or less redundant, and the best performance is not considered. Readers who are interested can further simplify it!

The details are as follows:

(1)main.c

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include"seqList.h"
#include"queue.h"

void swap(int *arr, int a, int b)
{
	int t = arr[a];
	arr[a] = arr[b];
	arr[b] = t;
}
//Bubble sorting implementation method of exchange sorting
void bubbleSort(int *arr, int n)
{
	//Compare adjacent elements
	//First traversal range: 0 ~ the last position of unordered data
	int m = n; 
	while (m>1)//Normally, the number of steps per cycle is 6 5 4 3 2 1 = 21
	{
		//flag: marks whether a swap operation has occurred in a round of bubble sorting
		int flag = 0;
		for (int j = 1; j < m; j++)
		{
			if (arr[j-1] > arr[j])
			{
				swap(arr, j-1, j);
				flag = 1;
			}
		}
		//If no exchange occurs, the remaining elements are all in order -- improving performance
		if (!flag)
			break;
		m--;
	}
	
	/*for (int i = 0; i < n; i++)
	{
		for (int j = i; j < n; j++)
		{
			if (arr[j - 1] > arr[j])
			{
				swap(arr, j - 1, j);
			}
			h++;
		}
	}
	printf("h = %d \n", h);*/
}

//hoare improvement: obtain the benchmark value: three number middle method, start, middle and end
int getMid(int *arr, int begin, int end)
{
	int mid = begin + (end - begin) / 2;
	if (arr[begin] >= arr[mid])
	{
		if (arr[mid] >= arr[end])  // arr[begin]>arr[mid]>arr[end]
			return mid;
		else if (arr[begin] <= arr[end])//arr[end]>arr[begin]>=arr[mid]
			return begin;
		else  // arr[begin]>arr[end]>arr[mid]
			return end;
	}
	else//arr[begin] < arr[mid]
	{
		if (arr[mid] <= arr[end])//arr[begin] < arr[mid] <arr[end]
			return mid;
		else if (arr[begin] >= arr[end])//arr[end]<=arr[begin]<arr[mid]
			return begin;
		else //arr[end]<arr[begin]<arr[mid]
			return end;
	}
}

//Pit digging method of exchange sequencing
int partion2(int *arr, int begin, int end)
{
	//Get the location of the reference value
	int mid = getMid(arr, begin, end);
	//Put the reference value at the starting position
	swap(arr, begin, mid);
	//The first value is used as the reference value, and the first position is the position of the initial pit
	int key = arr[begin];
	//int start = begin;
	while (begin < end)
	{
		//int key = start;
		//Find the position less than the reference value from back to front
		while (begin < end && arr[end] >= key)
			--end;
		//Pit filling
		arr[begin] = arr[end];

		//Find the position greater than the reference value from front to back
		while (begin < end && arr[begin] <= key)
			++begin;
		//Pit filling
		arr[end] = arr[begin];
	}
	//Place the encounter position into the reference value
	arr[begin] = key;
	return begin;
}

//Before and after pointer method of exchange sorting
int partion3(int *arr, int begin, int end)
{
	//Last position less than the reference value
	int prev = begin;
	//Next position less than the reference value
	int cur = begin + 1;
	int key = arr[begin];
	while (cur <= end)
	{
		//When prev and cur are discontinuous, exchange the two numbers and judge the continuity first
		if (arr[cur] < key && ++prev != cur)//Discontinuity
		{
			//Discontinuous, exchange two data
			swap(arr, prev, cur);
		}
		++cur;
	}
	//Exchange reference value and prev value
	swap(arr, begin, prev);
	return prev;
}

//Quick sorting of exchange sorting: hoare method
//Returns the position of the benchmark value after division
int partion(int *arr, int begin, int end)
{
	//Get the location of the reference value
	int mid = getMid(arr, begin, end);
	//Put the reference value at the starting position
	swap(arr, begin, mid);  
	//Select reference value
	int key = arr[begin];
	int start = begin;
	while (begin < end)
	{
		//Find the position less than the reference value from back to front
		while (begin < end && arr[end] >= key)
			--end;
		//Find the position greater than the reference value from front to back
		while (begin < end && arr[begin] <= key)
			++begin;
		//exchange
		swap(arr, begin, end);
	}
	//Exchange the data of reference value and encounter position after completion
	swap(arr, start, begin);
	return begin;
}

//Recursive fast scheduling
void quickSort(int *arr, int begin, int end)//Implementation of hoare
{
	if (begin >= end)
		return;
	//div: position of reference value after one division
	int div = partion3(arr, begin, end);
	//Quickly sort the left and right parts
	//[begin,div-1]
	//[div+1,end]
	quickSort(arr, begin, div - 1);
	quickSort(arr, div + 1, end);
	
}

/*Sequence table for non recursive fast scheduling   */
void quickSortNor(int *arr, int n)
{
	//Create a sequence table and save the intervals to be divided
	SeqList sq;
	initseqList(&sq);
	//First save the entire interval   
	//First on the right, then on the left
	seqListPushBack(&sq, n - 1);
	seqListPushBack(&sq, 0);
	//Traverse the sequence table and process all intervals
	while (!seqListEmpty(&sq))//Only when it is not empty can the program run!!!!!!!!!!!
	{
		//Take out an interval
		int left = seqListBack(&sq);
		seqListPopBack(&sq);
		int right = seqListBack(&sq);
		seqListPopBack(&sq);

		//Partition interval [left,right]
		int div = partion(arr, left, right);

		//Save the generated two new areas
		//[left,div-1]
		if (left < div - 1)
		{
			seqListPushBack(&sq, div - 1);
			seqListPushBack(&sq, left);
		}
		//[div+1,right]
		if (div + 1 < right)
		{
			seqListPushBack(&sq, right);
			seqListPushBack(&sq, div + 1);
		}
	}
}
/*Non recursive fast queue     */
void quickSortNor2(int *arr, int n)
{
	//Create a queue and save the interval to be divided
	Queue q;
	initQueue(&q);

	//First save the entire interval queue: first in first out 
	//First on the right, then on the left
	queuePush(&q, 0);
	queuePush(&q, n - 1);
	
	//Traverse the queue and process all intervals
	while (!queueEmpty(&q))//Only when it is not empty can the program run!!!!!!!!!!!
	{
		//Take out an interval
		int left = queueFront(&q);
		queuePop(&q);
		int right = queueFront(&q);
		queuePop(&q);

		//Partition interval [left,right]
		int div = partion(arr, left, right);

		//Save the generated two new areas
		//[left,div-1]
		if (left < div - 1)
		{
			queuePush(&q, left);
			queuePush(&q, div - 1);
		}
		//[div+1,right]
		if (div + 1 < right)
		{
			queuePush(&q, div + 1);
			queuePush(&q, right);
		}
	}
}


//Merge sort!!!!!!!!!
//Merging of adjacent subsequences: begin end + 1 end2
void merge(int *arr, int begin, int mid, int end, int *tmp)
{
	//Increasing
	//Subinterval: [begin,mid] [mid+1,end]
	int begin1 = begin;
	int end1 = mid;
	int begin2 = mid + 1;
	int end2 = end;

	//Starting position of auxiliary space
	int idx = begin;

	//Merge ordered sequence
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (arr[begin1] <= arr[begin2])
			tmp[idx++] = arr[begin1++];
		else
			tmp[idx++] = arr[begin2++];
	}
	//Determine whether there are unconsolidated elements
	if (begin1 <= end1)
		memcpy(tmp + idx, arr + begin1, sizeof(int)*(end1 - begin1 + 1));
	if (begin2 <= end2)
		memcpy(tmp + idx, arr + begin2, sizeof(int)*(end2 - begin2 + 1));

	//The merged sequence is copied to the corresponding interval of the original data
	memcpy(arr + begin, tmp + begin, sizeof(int)*(end - begin + 1));
}
//Time complexity: o(nlogn) stable
/* Merge recursion */
void _mergeSort(int *arr, int begin, int end, int *tmp)
{
	if (begin >= end)
		return;

	int mid = begin + (end - begin) / 2;

	//First merge subsequences
	_mergeSort(arr, begin, mid, tmp);
	_mergeSort(arr, mid + 1, end, tmp);

	//Merge two ordered subsequences
	merge(arr, begin, mid, end, tmp);
}
void mergeSort(int *arr, int n)//recursion
{
	//Apply for auxiliary space
	int *tmp = (int *)malloc(sizeof(int)*n);
	_mergeSort(arr, 0, n - 1, tmp);
	free(tmp);
}
/* Return is not recursive */
void mergeSortNor(int *arr, int n)//non-recursive 
{
	int *tmp = (int *)malloc(sizeof(int)*n);
	//Step size of subsequence
	int step = 1;
	while (step < n)
	{
		//Deal with small sequences first, and then deal with large ones
		for (int idx = 0; idx < n; idx += 2 * step)
		{
			//Find two subsequence intervals to be merged
			//[begin,mid] [mid+1,end]
			int begin = idx;
			int mid = idx + step - 1;
			//Determine whether there is a second subsequence
			if (mid >= n - 1)
				//There is no second subsequence, skip directly
				continue;
			int end = idx + 2 * step - 1;
			//Judge whether the second subsequence is out of bounds
			if (end >= n)
				end = n - 1;
			merge(arr, begin, mid, end, tmp);
		}

		//Update step
		step *= 2;
	}
	//free(tmp);
}

//Non comparative sort -- count sort
//Time complexity: O(Max(n,range))
//Space complexity: O(range) if the scope is very large, the waste of space is huge, such as 0 1 2 10000000
void countSort(int *arr, int n)
{
	//Find maximum and minimum values
	int max, min;
	min = max = arr[0];
	for (int i = 1; i < n; i++)
	{
		if (arr[i] > max)
			max = arr[i];
		if (arr[i] < min)
			min = arr[i];
	}
	//Calculate the number range of count array
	int range = max - min + 1;
	//Create a count array and initialize it to 0
	int *countArr = (int *)calloc(range,sizeof(int));

	//Count calculates the number of identical numbers in the arr
	for (int i = 0; i < n; ++i)
	{
		countArr[arr[i] - min]++;
	}

	//Traverse count array, sort
	int idx = 0;
	for (int i = 0; i < range; i++)
	{
		while (countArr[i]--)
		{
			arr[idx++] = i + min;
		}
	}
}

//Print array
 void printArr(int *arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}printf("\n");
}

void test()
{
	int arr1[] = { 6, 3, 1, 8, 7, 2, 4 };
	int n = sizeof(arr1) / sizeof(arr1[0]);
	int *arr2 = (int*)malloc(sizeof(int)*n);
	memcpy(arr2, arr1, sizeof(arr1));
	printf("Contents before sorting:\n");
	printArr(arr2, n); printf("\n");

	printf("Contents after bubble sorting:\n");
	bubbleSort(arr2, n);
	printArr(arr2, n); printf("\n");
	memcpy(arr2, arr1, sizeof(arr1));

	printf("Content after recursive fast scheduling:\n");
	quickSort(arr2, 0, n - 1);
	printArr(arr2, n); printf("\n");
	memcpy(arr2, arr1, sizeof(arr1));

	printf("Contents after non recursive fast scheduling (using sequence table):\n");
	quickSortNor(arr2,  n);
	printArr(arr2, n); printf("\n");
	memcpy(arr2, arr1, sizeof(arr1));

	printf("Content after non recursive fast queuing (using queue):\n");
	quickSortNor2(arr2,  n );
	printArr(arr2, n); printf("\n");
	memcpy(arr2, arr1, sizeof(arr1));

	printf("Content after recursive merging and sorting:\n");
	mergeSort(arr2, n );
	printArr(arr2, n);printf("\n");
	memcpy(arr2, arr1, sizeof(arr1));

	printf("Contents after non recursive merging and sorting:\n");
	mergeSortNor(arr2,  n);
	printArr(arr2, n); printf("\n");
	memcpy(arr2, arr1, sizeof(arr1));

	printf("Contents after non comparison sorting:\n");
	countSort(arr2, n);
	printArr(arr2, n); printf("\n");
	memcpy(arr2, arr1, sizeof(arr1));
}

//void test2()
//{
//	int n;
//	printf("amount of data: \ n");
//	scanf_s("%d", &n);
//	srand(time(NULL));
//	int *arr = (int *)malloc(sizeof(int)*n);
//	int *copy1 = (int *)malloc(sizeof(int)*n);
//	int *copy2 = (int *)malloc(sizeof(int)*n);
//	for (int i = 0; i < n; i++)
//	{
//		arr[i] = rand();
//	}
//	memcpy(copy1, arr, sizeof(int)*n);
//	memcpy(copy2, arr, sizeof(int)*n);
//
//	time_t begin = clock();
//	insert(copy1, n);
//	time_t end = clock();
//	printf("direct insert sort time:% d\n", end - begin);
//
//	begin = clock();
//	shellSort(copy2, n);
//	end = clock();
//	printf("Hill sort time:% d\n", end - begin);
//}
int main()
{
	test();
	system("pause");
	return 0;
}

(2) Operation results

Infringement deletion~

Topics: C Algorithm data structure linked list queue