30/09/2018, 16:31

Cách nhanh có thật sự nhanh trong sắp xếp mảng 2 chiều

Sắp xếp các phần tử trên mảng 2 chiều tăng dần từ trên xuống dưới và từ trái sang phải.

Theo mình được biết là có 2 ý tưởng cho bài này


Ý tưởng 1: Đối với người chưa biết dùng 1 vòng lặp để duyệt mảng 2 chiều sẽ làm như sau:
Bước 1: Đọc tất cả các phần tử trong mảng 2 chiều hiện tại sang 1 mảng 1 chiều.
Bước 2: Sắp xếp mảng 1 chiều đó tăng dần.
Bước 3: Từ mảng 1 chiều tăng dần, đọc lại vào mảng 2 chiều.

void SapXepMang2ChieuTangDan_Cach1(int a[][MAX], int SoDong, int SoCot)
{
	int n = 0;
	int b[MAX];
	for(int i = 0; i < SoDong; i++)
	{
		for(int j = 0; j < SoCot; j++)
		{
			b[n] = a[i][j];
			n++; 
		}
	}
	SapXepMang1ChieuTangDan(b, n);
	n = 0; 
	for(int i = 0; i < SoDong; i++)
	{
		for(int j = 0; j < SoCot; j++)
		{
			a[i][j] = b[n];
			n++;
		}
	}
}

Và đây là ý tưởng 2 : Đối với người biết cách dùng 1 vòng lặp duyệt mảng 2 chiều.
=> Làm như bên mảng 1 chiều.

void SapXepMang2ChieuTangDan_Cach2(int a[][MAX], int SoDong, int SoCot)
{
	int n = SoDong * SoCot;

	for(int i = 0; i < n - 1; i++)
	{
		for(int j = i + 1; j < n; j++)
		{
			if(a[i / SoCot][i % SoCot] > a[j / SoCot][j % SoCot])
			{
				HoanVi(a[i / SoCot][i % SoCot], a[j / SoCot][j % SoCot]);
			}
		}
	}
}

Nhìn thì ai cũng biết là cách 1 tốn bộ nhớ và nó chậm hơn cách 2 rất là nhiều ( đại ca Nguyễn Việt Nam Sơn cũng nói thế)
Nhưng khi dùng hàm đo thời gian thì lại xãy ra chuyện là cách 2 lại chạy chậm hơn cách 1


Dẫn chứng

/* ============== Đo Thời Gian Cách 1 ============== */
	
	clock_t start1 = clock();

	for(int i = 1; i <= 10000000; i++)
	{
		SapXepMang2ChieuTangDan_Cach1(a, SoDong, SoCot);
	}

	clock_t finish1 = clock();
	/* ================================================= */
/* ============== Đo Thời Gian Cách 2 ============== */
	clock_t start2 = clock();

	for(int i = 1; i <= 10000000; i++)
	{
		SapXepMang2ChieuTangDan_Cach2(a, SoDong, SoCot);
	}

	clock_t finish2  = clock();
	/* ================================================= */

TẠI SAO NHĨ PHẢI CHĂNG CÁCH 1 VẪN LÀ CÁCH NHANH NHẤT HAY HÀM KIỂM TRA THỜI GIAN ĐÃ DÙNG KHÔNG ĐÚNG

Và mình cũng thắc mắc rất nhiều nên mới đem lên đây và mong nhận được cao kiến của anh chị em,và đây là lần đầu tiên em đăng bài lên diễn đàn nếu có gì sai xót mong anh chị góp ý

Minh Hoàng viết 18:46 ngày 30/09/2018

Nhìn thì ai cũng biết là cách 1 tốn bộ nhớ và nó chậm hơn cách 2 rất là nhiều

Mình thì không biết Mệnh đề này không ổn nè
Mình thấy cái cách 2 phải tính toán vị trí của mỗi lần so sánh

Gió viết 18:41 ngày 30/09/2018

Mình không hiểu bạn đang so sánh thuật toán sắp xếp kiểu gì?

int n = 0;

Trong đoạn code này n= dong * cot . Thì độ phức tạp của thuật toán phụ thuộc vào hàm nay:

SapXepMang1ChieuTangDan(b, n);

Nếu dùng quick_sort thì có thể chạy trong nlogn

int n = SoDong * SoCot;

	for(int i = 0; i &lt; n - 1; i++)
	{
		for(int j = i + 1; j &lt; n; j++)
		{
			if(a[i / SoCot][i % SoCot] &gt; a[j / SoCot][j % SoCot])
			{
				HoanVi(a[i / SoCot][i % SoCot], a[j / SoCot][j % SoCot]);
			}
		}
	}

thuật toán này là select sort chạy 2 vòng for trong n^2 thì tất nhiên phải lâu hơn trong TH 1.

leni viết 18:38 ngày 30/09/2018

đến khi xuất ma trận mới sắp xếp không được là sao ạ?

Mai Hữu viết 18:34 ngày 30/09/2018

Bản chất của mảng hai chiều là gồm cách mảng một chiều ghép lại. Nếu sắp xếp theo đề của bạn thì bạn có thể xài cách này. Mình đảm bảo nhanh hơn 2 cách của bạn
void SapXepMang2Chieu(int mangHaiChieu[][MAX],int m,int n)
{
int doDai=m*n;
for(int i=0;i<doDai;i++)
{
for(int j=i;j<doDai;j++)
{
if(mangHaiChieu[i]<mangHaiChieu[j]) HoanVi(mangHaiChieu[i],mangHaiChieu[j]);
}
}
}

Bài liên quan
0