JavaRush /جاوا بلاگ /Random-SD /نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ
Viacheslav
سطح

نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ

گروپ ۾ شايع ٿيل
ترتيب ڏيڻ هڪ بنيادي قسم جي سرگرمين يا عملن مان هڪ آهي جيڪو شين تي ڪيو ويندو آهي. جيتوڻيڪ ننڍپڻ ۾، ٻارن کي ترتيب ڏيڻ سيکاريو ويندو آهي، انهن جي سوچ کي ترقي ڪندي. ڪمپيوٽر ۽ پروگرام به ڪو استثنا نه آهن. الورورٿم جي هڪ وڏي قسم آهن. مان توهان کي صلاح ڏيان ٿو ته اهي ڇا آهن ۽ اهي ڪيئن ڪم ڪن ٿا. ان سان گڏ، ڇا جيڪڏهن هڪ ڏينهن توهان هڪ انٽرويو ۾ انهن مان هڪ بابت پڇيو؟
نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ - 1

تعارف

عناصر کي ترتيب ڏيڻ الورورٿم جي قسمن مان هڪ آهي جنهن کي ڊولپر کي استعمال ڪرڻ گهرجي. جيڪڏهن ڪنهن زماني ۾، جڏهن آئون پڙهندو هوس، ڪمپيوٽر سائنس کي ايترو سنجيده نه ورتو ويندو هو، هاڻي اسڪول ۾ انهن کي ترتيب ڏيڻ جي الگورتھم کي لاڳو ڪرڻ ۽ انهن کي سمجهڻ گهرجي. بنيادي الگورتھم، آسان ترين، لوپ استعمال ڪندي لاڳو ڪيا ويا آھن for. قدرتي طور تي، عناصر جي مجموعي کي ترتيب ڏيڻ لاء، مثال طور، هڪ صف، توهان کي ڪنهن به طرح هن مجموعي کي پار ڪرڻ جي ضرورت آهي. مثال طور:
int[] array = {10, 2, 10, 3, 1, 2, 5};
for (int i = 0; i < array.length; i++) {
	System.out.println(array[i]);
}
توهان ڪوڊ جي هن ٽڪرا بابت ڇا چئي سگهو ٿا؟ اسان وٽ هڪ لوپ آهي جنهن ۾ اسان انڊيڪس ويليو ( int i) کي 0 کان آخري عنصر تائين تبديل ڪندا آهيون. لازمي طور تي، اسان صرف هر عنصر کي صف ۾ وٺي رهيا آهيون ۽ ان جي مواد کي ڇپائي رهيا آهيون. صف ۾ وڌيڪ عناصر، ڪوڊ وڌيڪ وقت تي عمل ڪرڻ لاء وٺندو. اهو آهي، جيڪڏهن n عناصر جو تعداد آهي، n = 10 سان پروگرام n = 5 جي ڀيٽ ۾ 2 ڀيرا وڌيڪ وقت وٺندو. جڏهن اسان جي پروگرام ۾ هڪ لوپ آهي، عملدرآمد جو وقت لڪيريء سان وڌي ٿو: وڌيڪ عناصر، وڌيڪ عملدرآمد. اهو ظاهر ٿئي ٿو ته مٿي ڏنل ڪوڊ جو الگورتھم لڪير واري وقت ۾ ڪم ڪري ٿو (n). اهڙين حالتن ۾، "الگورٿم پيچيدگي" کي O (n) چيو ويندو آهي. اهو اشارو پڻ سڏيو ويندو آهي "وڏو O" يا "asymptotic رويي". پر توهان صرف ياد ڪري سگهو ٿا "الورورٿم جي پيچيدگي."
نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ - 2

آسان ترين ترتيب (بلبل ترتيب)

تنهن ڪري، اسان وٽ هڪ صف آهي ۽ ان تي ٻيهر ڪري سگهون ٿا. زبردست. اچو ته ھاڻي ڪوشش ڪريون ان کي وڌندي ترتيب ۾ ترتيب ڏيو. اهو اسان لاء ڇا مطلب آهي؟ هن جو مطلب اهو آهي ته ڏنل ٻه عنصر (مثال طور، a = 6، b = 5)، اسان کي تبديل ڪرڻ گهرجي a ۽ b جيڪڏهن a b کان وڏو آهي (جيڪڏهن a > b). اهو اسان لاءِ ڇا مطلب آهي جڏهن انڊيڪس ذريعي گڏ ڪرڻ سان ڪم ڪري رهيو آهي (جيئن ته هڪ صف سان معاملو آهي)؟ هن جو مطلب اهو آهي ته جيڪڏهن عنصر انڊيڪس a سان انڊيڪس بي سان عنصر کان وڏو آهي، (array[a] > array[b])، اهڙن عناصر کي تبديل ڪيو وڃي. جڳهن کي تبديل ڪرڻ اڪثر ڪري ادل سڏيو ويندو آهي. جڳهن کي تبديل ڪرڻ جا مختلف طريقا آهن. پر اسان استعمال ڪندا آهيون سادو، صاف ۽ ياد رکڻ ۾ آسان ڪوڊ:
private void swap(int[] array, int ind1, int ind2) {
    int tmp = array[ind1];
    array[ind1] = array[ind2];
    array[ind2] = tmp;
}
ھاڻي اسان ھيٺيون ڳالھيون لکي سگھون ٿا:
int[] array = {10, 2, 10, 3, 1, 2, 5};
System.out.println(Arrays.toString(array));
for (int i = 1; i < array.length; i++) {
	if (array[i] < array[i - 1]) {
		swap(array, i, i-1);
	}
}
System.out.println(Arrays.toString(array));
جيئن اسان ڏسي سگهون ٿا، عناصر واقعي جڳهن کي تبديل ڪيو آهي. اسان هڪ عنصر سان شروع ڪيو، ڇاڪاڻ ته ... جيڪڏهن صف صرف هڪ عنصر تي مشتمل آهي، اظهار 1 <1 صحيح نه موٽندو ۽ اهڙي طرح اسان پاڻ کي هڪ عنصر سان يا انهن جي بغير ڪنهن صف جي ڪيسن کان بچائي سگهنداسين، ۽ ڪوڊ بهتر نظر ايندو. پر اسان جي آخري صف ڪنهن به طرح ترتيب نه آهي، ڇاڪاڻ ته ... اهو ممڪن ناهي ته سڀني کي هڪ پاس ۾ ترتيب ڏيو. اسان کي هڪ ٻيو لوپ شامل ڪرڻو پوندو جنهن ۾ اسان هڪ هڪ ڪري پاسن کي انجام ڏينداسين جيستائين اسان کي ترتيب ڏنل صف نه ملي.
int[] array = {10, 2, 10, 3, 1, 2, 5};
System.out.println(Arrays.toString(array));
boolean needIteration = true;
while (needIteration) {
	needIteration = false;
	for (int i = 1; i < array.length; i++) {
		if (array[i] < array[i - 1]) {
			swap(array, i, i-1);
			needIteration = true;
		}
	}
}
System.out.println(Arrays.toString(array));
تنهنڪري اسان جي پهرين ترتيب ڪم ڪيو. اسان ٻاهرئين لوپ ( while) ۾ ٻيهر ورجائيندا آهيون جيستائين اسان اهو فيصلو نه ڪريون ته وڌيڪ ٻيهر ورجائڻ جي ضرورت ناهي. ڊفالٽ طور، هر نئين ورهاڱي کان اڳ، اسان فرض ڪريون ٿا ته اسان جي صف کي ترتيب ڏني وئي آهي، ۽ اسان کي وڌيڪ ٻيهر ڪرڻ نٿا چاهيون. تنهن ڪري، اسان عناصر جي ترتيب سان وڃو ۽ هن مفروضي کي چيڪ ڪريو. پر جيڪڏهن عناصر ترتيب کان ٻاهر آهن، اسان عناصر کي تبديل ڪريون ٿا ۽ سمجهون ٿا ته اسان کي پڪ ناهي ته عناصر هاڻي صحيح ترتيب ۾ آهن. تنهن ڪري، اسان هڪ وڌيڪ ورجائي انجام ڏيڻ چاهيون ٿا. مثال طور، [3، 5، 2]. 5 ٽن کان وڌيڪ آهي، سڀ ڪجهه ٺيڪ آهي. پر 2 5 کان گهٽ آهي. جڏهن ته، [3، 2، 5] هڪ وڌيڪ پاس جي ضرورت آهي، ڇاڪاڻ ته 3 > 2 ۽ انهن کي تبديل ڪرڻ جي ضرورت آهي. جيئن ته اسان لوپ اندر لوپ استعمال ڪندا آهيون، اهو ظاهر ٿئي ٿو ته اسان جي الگورتھم جي پيچيدگي وڌائي ٿي. n عناصر سان اهو n * n ٿيندو، اهو آهي O (n^2). هن پيچيدگي کي quadratic سڏيو ويندو آهي. جيئن اسان سمجھون ٿا، اسان ڄاڻ نه ٿا سگھون ته ڪيترين ئي ورهاڱي جي ضرورت پوندي. الورورٿم پيچيدگي اشاري کي وڌائڻ جي پيچيدگي جي رجحان کي ڏيکارڻ جو مقصد ڪم ڪري ٿو، بدترين صورت. هلندڙ وقت ڪيترو وڌي ويندو جڏهن عنصرن جو تعداد تبديل ٿيندو. بلبل جي ترتيب هڪ سادي ۽ سڀ کان وڌيڪ غير موثر قسمن مان هڪ آهي. اهو پڻ ڪڏهن ڪڏهن سڏيو ويندو آهي "بيوقوف ترتيب". لاڳاپيل مواد:
نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ - 3

چونڊ ترتيب

ٻيو قسم آهي چونڊ ترتيب. ان ۾ پڻ quadratic پيچيدگي آهي، پر ان تي وڌيڪ بعد ۾. تنهنڪري خيال سادو آهي. هر پاس ننڍڙو عنصر چونڊيندو آهي ۽ ان کي شروعات ڏانهن منتقل ڪندو آهي. انهي حالت ۾، هر نئين پاس کي ساڄي طرف منتقل ڪندي شروع ڪريو، اهو آهي، پهريون پاس - پهرين عنصر کان، ٻيو پاس - سيڪنڊ کان. اهو هن طرح نظر ايندو:
int[] array = {10, 2, 10, 3, 1, 2, 5};
System.out.println(Arrays.toString(array));
for (int left = 0; left < array.length; left++) {
	int minInd = left;
	for (int i = left; i < array.length; i++) {
		if (array[i] < array[minInd]) {
			minInd = i;
		}
	}
	swap(array, left, minInd);
}
System.out.println(Arrays.toString(array));
هي ترتيب غير مستحڪم آهي، ڇاڪاڻ ته هڪجهڙا عنصر (خاصيت جي نقطي نظر کان جنهن جي ذريعي اسان عناصر کي ترتيب ڏيو ٿا) انهن جي پوزيشن کي تبديل ڪري سگهي ٿو. ھڪڙو سٺو مثال وڪيپيڊيا مضمون ۾ ڏنو ويو آھي: ترتيب ڏيڻ_جي چونڊ . لاڳاپيل مواد:
نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ - 4

داخل ڪرڻ جي ترتيب

داخل ڪرڻ جي ترتيب ۾ پڻ quadratic پيچيدگي آهي، ڇاڪاڻ ته اسان وٽ وري هڪ لوپ اندر هڪ لوپ آهي. اهو ڪيئن مختلف آهي چونڊ ترتيب کان؟ هي ترتيب "مستحڪم" آهي. هن جو مطلب آهي ته هڪجهڙائي عنصرن سندن ترتيب تبديل نه ڪندو. خاصيتن جي لحاظ کان هڪجهڙائي جنهن سان اسان ترتيب ڏيون ٿا.
int[] array = {10, 2, 10, 3, 1, 2, 5};
System.out.println(Arrays.toString(array));
for (int left = 0; left < array.length; left++) {
	// Retrieve the value of the element
	int value = array[left];
	// Move through the elements that are before the pulled element
	int i = left - 1;
	for (; i >= 0; i--) {
		// If a smaller value is pulled out, move the larger element further
		if (value < array[i]) {
			array[i + 1] = array[i];
		} else {
			// If the pulled element is larger, stop
			break;
		}
	}
	// Insert the extracted value into the freed space
	array[i + 1] = value;
}
System.out.println(Arrays.toString(array));
لاڳاپيل مواد:
نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ - 5

شٽل جي ترتيب

سادي قسمن جي وچ ۾، ھڪڙو ٻيو آھي - شٽل ترتيب ڏيڻ. پر مان شٽل قسم کي ترجيح ڏيان ٿو. اهو مون کي لڳي ٿو ته اسان گهٽ ۾ گهٽ خلائي شٽل بابت ڳالهايون ٿا، ۽ شٽل وڌيڪ ڊوڙندو آهي. تنهن ڪري، اهو تصور ڪرڻ آسان آهي ته ڪيئن شٽل خلا ۾ شروع ڪيا ويا آهن. هتي هن الگورتھم سان تعلق آهي. الورورٿم جو جوهر ڇا آهي؟ الورورٿم جو جوهر اهو آهي ته اسين کاٻي کان ساڄي طرف ٻيهر ورجايون ٿا، ۽ جڏهن عناصر کي مٽائي رهيا آهيون، اسان ٻين سڀني عنصرن کي چيڪ ڪريون ٿا جيڪي پوئتي رهجي ويا آهن اهو ڏسڻ لاءِ ته ڇا ادل بدلائڻ جي ضرورت آهي.
int[] array = {10, 2, 10, 3, 1, 2, 5};
System.out.println(Arrays.toString(array));
for (int i = 1; i < array.length; i++) {
	if (array[i] < array[i - 1]) {
		swap(array, i, i - 1);
		for (int z = i - 1; (z - 1) >= 0; z--) {
			if (array[z] < array[z - 1]) {
				swap(array, z, z - 1);
			} else {
				break;
			}
		}
	}
}
System.out.println(Arrays.toString(array));
لاڳاپيل مواد:
نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ - 6

شيل جي ترتيب

ٻيو سادو قسم آهي شيل ترتيب. ان جو جوهر بلبل جي ترتيب سان ملندڙ جلندڙ آهي، پر هر هڪ ورهاڱي ۾ اسان جي مقابلي ۾ عناصر جي وچ ۾ مختلف فرق آهي. هر ورجائي ان کي اڌ ڪيو ويندو آهي. هتي هڪ مثال لاڳو ڪرڻ آهي:
int[] array = {10, 2, 10, 3, 1, 2, 5};
System.out.println(Arrays.toString(array));
// Calculate the gap between the checked elements
int gap = array.length / 2;
// As long as there is a difference between the elements
while (gap >= 1) {
    for (int right = 0; right < array.length; right++) {
        // Shift the right pointer until we can find one that
        // there won't be enough space between it and the element before it
       for (int c = right - gap; c >= 0; c -= gap) {
           if (array[c] > array[c + gap]) {
               swap(array, c, c + gap);
           }
        }
    }
    // Recalculate the gap
    gap = gap / 2;
}
System.out.println(Arrays.toString(array));
لاڳاپيل مواد:
نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ - 7

ضم ڪرڻ جي ترتيب

ظاهر ڪيل سادي قسمن کان علاوه، وڌيڪ پيچيده قسمون آهن. مثال طور، ضم ڪرڻ جي ترتيب. پهرين، ورجائي اسان جي مدد لاء ايندي. ٻيو ته، اسان جي پيچيدگي هاڻي quadratic نه ٿيندي، جيئن اسان کي استعمال ڪيو ويو آهي. هن الگورتھم جي پيچيدگي logarithmic آهي. O (n log n) جي طور تي لکيل آهي. سو اچو ته اهو ڪريون. پهرين، اچو ته ترتيب ڏيڻ واري طريقي کي ٻيهر ورجائي ڪال لکون:
public static void mergeSort(int[] source, int left, int right) {
        // Choose a separator, i.e. split the input array in half
        int delimiter = left + ((right - left) / 2) + 1;
        // Execute this function recursively for the two halves (if we can split(
        if (delimiter > 0 && right > (left + 1)) {
            mergeSort(source, left, delimiter - 1);
            mergeSort(source, delimiter, right);
        }
}
هاڻي اچو ته ان ۾ هڪ بنيادي عمل شامل ڪريون. هتي عمل درآمد سان اسان جي سپر ميٿڊ جو هڪ مثال آهي:
public static void mergeSort(int[] source, int left, int right) {
        // Choose a separator, i.e. split the input array in half
        int delimiter = left + ((right - left) / 2) + 1;
        // Execute this function recursively for the two halves (if we can split(
        if (delimiter > 0 && right > (left + 1)) {
            mergeSort(source, left, delimiter - 1);
            mergeSort(source, delimiter, right);
        }
        // Create a temporary array with the desired size
        int[] buffer = new int[right - left + 1];
        // Starting from the specified left border, go through each element
        int cursor = left;
        for (int i = 0; i < buffer.length; i++) {
            // We use the delimeter to point to the element from the right side
            // If delimeter > right, then there are no unadded elements left on the right side
            if (delimiter > right || source[cursor] > source[delimiter]) {
                buffer[i] = source[cursor];
                cursor++;
            } else {
                buffer[i] = source[delimiter];
                delimiter++;
            }
        }
        System.arraycopy(buffer, 0, source, left, buffer.length);
}
اچو ته مثال کي ڪال ڪندي هلون mergeSort(array, 0, array.length-1). جئين توهان ڏسي سگهو ٿا، جوهر حقيقت تي اچي ٿو ته اسان ان پٽ جي طور تي هڪ ايري وٺون ٿا جيڪو ترتيب ڏيڻ لاء سيڪشن جي شروعات ۽ پڇاڙيء کي ظاهر ڪري ٿو. جڏهن ترتيب ڏيڻ شروع ٿئي ٿي، هي صف جي شروعات ۽ پڇاڙي آهي. اڳيون اسان ڊيليميٽر جي حساب سان - ورهائيندڙ جي پوزيشن. جيڪڏهن ورهائيندڙ کي 2 حصن ۾ ورهائي سگهجي ٿو، ته پوءِ اسين انهن حصن لاءِ ورهاست واري ترتيب کي سڏيندا آهيون جن ۾ ورهائيندڙ صف کي ورهايو آهي. اسان هڪ اضافي بفر صف تيار ڪريون ٿا جنهن ۾ اسان ترتيب ڏنل سيڪشن کي چونڊيو ٿا. اڳيون، اسان ڪرسر کي ترتيب ڏيڻ واري علائقي جي شروعات ۾ رکون ٿا ۽ خالي صف جي هر عنصر مان وڃڻ شروع ڪريون ٿا جيڪو اسان تيار ڪيو آهي ۽ ان کي ننڍن عناصر سان ڀريو. جيڪڏهن عنصر جيڪو ڪرسر جي طرف اشارو ڪيو ويو آهي ان عنصر کان ننڍو آهي جيڪو ڊيوزيزر جي طرف اشارو ڪيو ويو آهي، اسان هن عنصر کي بفر ايري ۾ رکون ٿا ۽ ڪرسر کي منتقل ڪريون ٿا. ٻي صورت ۾، اسان جدا ڪندڙ طرفان اشارو ڪيل عنصر کي بفر صف ۾ رکون ٿا ۽ جدا ڪندڙ کي منتقل ڪريو. جيئن ئي جدا ڪندڙ ترتيب ڏنل علائقي جي حدن کان ٻاهر نڪري ٿو يا اسان پوري صف کي ڀريون ٿا، مخصوص رينج کي ترتيب ڏنو وڃي ٿو. لاڳاپيل مواد:
نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ - 8

ڳڻپ جي ترتيب ۽ ريڊيڪس ترتيب

هڪ ٻيو دلچسپ ترتيب ڏيڻ وارو الگورتھم ڳڻڻ جي ترتيب آهي. هن معاملي ۾ الورورٿمڪ پيچيدگي O (n + k) هوندي، جتي n عناصر جو تعداد آهي، ۽ k عنصر جي وڌ ۾ وڌ قدر آهي. اتي ھڪڙو مسئلو آھي الگورتھم سان: اسان کي ڄاڻڻ جي ضرورت آھي گھٽ ۾ گھٽ ۽ وڌ ۾ وڌ قدر صف ۾. هتي ڳڻپ جي ترتيب جو هڪ مثال آهي:
public static int[] countingSort(int[] theArray, int maxValue) {
        // Array with "counters" ranging from 0 to the maximum value
        int numCounts[] = new int[maxValue + 1];
        // In the corresponding cell (index = value) we increase the counter
        for (int num : theArray) {
            numCounts[num]++;
        }
        // Prepare array for sorted result
        int[] sortedArray = new int[theArray.length];
        int currentSortedIndex = 0;
        // go through the array with "counters"
        for (int n = 0; n < numCounts.length; n++) {
            int count = numCounts[n];
            // go by the number of values
            for (int k = 0; k < count; k++) {
                sortedArray[currentSortedIndex] = n;
                currentSortedIndex++;
            }
        }
        return sortedArray;
    }
جيئن اسان سمجھون ٿا، اهو تمام ڏکيو آهي جڏهن اسان کي پهريان کان گهٽ ۾ گهٽ ۽ وڌ ۾ وڌ قدر ڄاڻڻو پوندو. ۽ پوء اتي هڪ ٻيو الگورتھم آهي - Radix ترتيب. آئون هتي صرف بصري طور تي الگورتھم پيش ڪندس. عمل ڪرڻ لاء، مواد ڏسو:
نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ - 9
مواد:
نظريي ۽ عمل ۾ الگورتھم کي ترتيب ڏيڻ - 10

جاوا جلدي ترتيب

خير، شيرين لاء - سڀ کان مشهور الگورتھم مان هڪ: جلدي ترتيب. ان ۾ الگورتھمڪ پيچيدگي آھي، اھو آھي، اسان وٽ O (n log n) آھي. هن قسم کي Hoare sort به چئبو آهي. دلچسپ ڳالهه اها آهي ته الورورٿم سوويت يونين ۾ رهڻ دوران هوئر پاران ايجاد ڪيو ويو، جتي هن ماسڪو يونيورسٽي ۾ ڪمپيوٽر جي ترجمي جو اڀياس ڪيو ۽ روسي-انگريزي جملي جو ڪتاب ٺاهي رهيو هو. هي الگورتھم جاوا ۾ Arrays.sort ۾ وڌيڪ پيچيده عمل ۾ پڻ استعمال ٿيندو آهي. Collections.sort بابت ڇا؟ مان صلاح ڏيان ٿو ته توهان پاڻ لاءِ ڏسو ته اهي ڪيئن ترتيب ڏنل آهن ”هوڊ هيٺ“. پوء، ڪوڊ:
public static void quickSort(int[] source, int leftBorder, int rightBorder) {
        int leftMarker = leftBorder;
        int rightMarker = rightBorder;
        int pivot = source[(leftMarker + rightMarker) / 2];
        do {
            // Move the left marker from left to right while element is less than pivot
            while (source[leftMarker] < pivot) {
                leftMarker++;
            }
            // Move the right marker until element is greater than pivot
            while (source[rightMarker] > pivot) {
                rightMarker--;
            }
            // Check if you don't need to swap elements pointed to by markers
            if (leftMarker <= rightMarker) {
                // The left marker will only be less than the right marker if we have to swap
                if (leftMarker < rightMarker) {
                    int tmp = source[leftMarker];
                    source[leftMarker] = source[rightMarker];
                    source[rightMarker] = tmp;
                }
                // Move markers to get new borders
                leftMarker++;
                rightMarker--;
            }
        } while (leftMarker <= rightMarker);

        // Execute recursively for parts
        if (leftMarker < rightBorder) {
            quickSort(source, leftMarker, rightBorder);
        }
        if (leftBorder < rightMarker) {
            quickSort(source, leftBorder, rightMarker);
        }
}
هتي سڀ ڪجهه تمام خوفناڪ آهي، تنهنڪري اسان ان کي سمجهنداسين. انپٽ ايري int[]ماخذ لاءِ، اسان ٻه نشان مقرر ڪيا، کاٻي (L) ۽ ساڄي (R). جڏهن پهريون ڀيرو سڏيو وڃي ٿو، اهي صف جي شروعات ۽ آخر سان ملن ٿا. اڳيون، معاون عنصر طئي ڪيو ويو آهي، عرف pivot. ان کان پوء، اسان جو ڪم آهي قدرن کي منتقل ڪرڻ کان گھٽ pivot، کاٻي ڏانهن pivot، ۽ وڏن کي ساڄي طرف. ھن کي ڪرڻ لاءِ، پھريائين پوائنٽر کي ھلايو Lجيستائين اسان کي ھڪ قدر نه ملي pivot. جيڪڏهن هڪ ننڍڙو قدر نه مليو، پوء L совпадёт с pivot. Потом двигаем указатель R пока не найдём меньшее, чем pivot meaning. Если меньшее meaning не нашли, то R совпадёт с pivot. Далее, если указатель L находится до указателя R or совпадает с ним, то пытаемся выполнить обмен элементов, если элемент L меньше, чем R. Далее L сдвигаем вправо на 1 позицию, R сдвигаем влево на одну позицию. Когда левый маркер L окажется за правым маркером R это будет означать, что обмен закончен, слева от pivot меньшие значения, справа от pivot — большие значения. После этого рекурсивно вызываем такую же сортировку для участков массива от начала сортируемого участка до правого маркера и от левого маркера до конца сортируемого участка. Почему от начала до правого? Потому что в конце итерации так и получится, что правый маркер сдвинется настолько, что станет границей части слева. Этот алгоритм более сложный, чем простая sorting, поэтому его лучше зарисовать. Возьмём белый лист бумаги, запишем: 4 2 6 7 3 , а Pivot по центру, т.е. число 6. Обведём его в круг. Под 4 напишем L, под 3 напишем R. 4 меньше чем 6, 2 меньше чем 6. Total, L переместился на положение pivot, т.к. по условию L не может уйти дальше, чем pivot. Напишем снова 4 2 6 7 3 , обведём 6 вкруг ( pivot) и поставим под ним L. Теперь двигаем указатель R. 3 меньше чем 6, поэтому ставим маркер R на цифру 3. Так How 3 меньше, чем pivot 6 выполняем swap, т.е. обмен. Запишем результат: 4 2 3 7 6 , обводим 6 вкруг, т.к. он по прежнему pivot. Указатель L на цифре 3, указатель R на цифре 6. Мы помним, что двигаем указатели до тех пор, пока L не зайдём за R. L двигаем на следующую цифру. Тут хочется разобрать два варианта: если бы предпоследняя цифра была 7 и если бы она была не 7, а 1. Предпоследня цифра 1: Сдвинули указатель L на цифру 1, т.к. мы можем двигать L до тех пор, пока указатель L указывает на цифру, меньшую чем pivot. А вот R мы не можем сдвинуть с 6, т.к. R не мы можем двигать только если указатель R указывает на цифру, которая больше чем pivot. swap не делаем, т.к. 1 меньше 6. Записываем положение: 4 2 3 1 6, обводим pivot 6. L сдвигается на pivot и больше не двигается. R тоже не двигается. Обмен не производим. Сдвигаем L и R на одну позицию и подписываем цифру 1 маркером R, а L получается вне числа. Т.к. L вне числа — ничего не делаем, а вот часть 4 2 3 1 выписываем снова, т.к. это наша левая часть, меньшая, чем pivot 6. Выделяем новый pivot и начинаем всё снова ) Предпоследняя цифра 7: Сдвинули указать L на цифру 7, правый указатель не можем двигать, т.к. он уже указывает на pivot. т.к. 7 больше, чем pivot, то делаем swap. Запишем результат: 4 2 3 6 7, обводим 6 кружком, т.к. он pivot. Указатель L теперь сдвигается на цифру 7, а указатель R сдвигается на цифру 3. Часть от L до конца нет смысла сортировать, т.к. там всего 1 элемент, а вот часть от 4 до указателя R отправляем на сортировку. Выбираем pivot и начинаем всё снова ) Может на первый взгляд показаться, что если расставить много одинаковых с pivot значений, это сломает алгоритм, но это не так. Можно напридумывать каверзных вариантов и на бумажке убедиться, что всё правильно и подивиться, How такие простые действия предоставляют такой надёжный механизм. Единственный минус — такая sorting не является стабильной. Т.к. при выполнении обмена одинаковые элементы могут поменять свой порядок, если один из них встретился до pivot до того, How другой элемент попал в часть до pivot при помощи обмена. Материал:

Итог

Выше мы рассмотрели "джентельменский" набор алгоритмов сортировки, реализованных на Java. Алгоритмы вообще штука полезная, How с прикладной точки зрения, так и с точки зрения развития мышления. Некоторые из них попроще, некоторые посложнее. По Howим-то умные люди защищали различные работы на степени, а по другим писали толстые-толстые книги. Надеюсь, приложенный к статье материал позволит вам узнать ещё больше, так How это обзорная статья, которая и так получилась увесистой. И цель её — дать небольшое вступление. Про введение в алгоритмы можно так же прочитать ознакомиться с книгой " Грокаем Алгоримы". Также мне нравится плэйлист от Jack Brown — AQA Decision 1 1.01 Tracing an Algorithm. Ради интереса можно посмотреть на визуализацию алгоритмов на sorting.at и visualgo.net. Ну и весь Youtube к вашим услугам.
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION