1. 程式人生 > 實用技巧 >the summury of array in C.

the summury of array in C.

這個作業屬於哪個班級 C語言--網路2011/2012
這個作業的地址 C語言部落格作業04--陣列
這個作業的目標 學習陣列相關內容
姓名 駱錕巨集

目錄

~~段首鳴謝好久沒有整整個了。

  1. 感謝這篇文章的作者,這裡引用過來作為拓展資料。淺談排序演算法

0. PTA上陣列題目的截圖:

1. 本章學習總結:

1.1 陣列中查詢的方法

1.1.1 順序查詢法:

  • 以PTA題目查詢整數為例:核心思想就是,遍歷陣列,然後讓陣列中的每一個數與目的數進行比較,如果存在相同的情況,那就記下陣列當中該數的下標,
    記下下標也就算是找到了該數。
      //順序查詢法,實質是遍歷陣列一一比較;
	for (Index = 0; Index < N; Index++)
	{
		if (a[Index] == X)
		{
			flag = 1;//此時表示已經找到
			loc = Index;
		}
	}
      //為了輸出方便一般會另設一個標記變數來標記找到與否。

1.1.2 二分查詢法:

  • 以課堂派的測試題為例:核心思想就是,讓這個數不斷和已知陣列中的中間數進行比較,每次比較過後縮減一半的範圍,直到最後無法再縮減,找到數字,或者
    陣列中不存在該數字,找不到。
//假設存在陣列a[],find表示要找的數,left表示左界的下標,right表示右界的下標。
	while (left < right)
	{
		middle = (left + right) / 2;
		if (find == a[middle])
		{
			printf("這個數是第%d個數", middle + 1);
			break;
		}
		else if (find > a[middle])
		{
			left = middle + 1;
		}
		else
		{
			right = middle - 1;
		}
	}

	if (left > right)
	{
		printf("找不到這個數");
	}

1.2 陣列中插入資料的方法

  • 陣列當中插入資料的辦法:往往是先找到需要插入的位置,然後從最後一個數字開始,
    慢慢地把數字一個一個,往後移動,最後空出插入的目的位置給需要插入的數字。
  • 但是要求是,陣列的長度要足夠長,必須要大於已經存在的數字和想要插入的數字的個數之和。
  • 如果要插入多個數字,只需要對要點一進行重複操作就行。
    以PTA中簡化的插入方式這道題為例可知:
      //判斷程式碼可以插入的位置;
	for (count = 0; count < numbN; count++)
	{
		if (numbX > a[count])
		{
			loc = count + 1;
		}
	}
	//將陣列中從這個位置開始向後移;
	for (countChange = numbN; countChange > loc; countChange--)
	{
		a[countChange] = a[countChange - 1];
	}
	a[loc] = numbX;

1.3 陣列中刪除資料的方法

1.3.1 簡單地刪除某幾個數:

  • 一種比較常見的方法就是 重構陣列,那就是先找到需要刪除的那個數的位置,然後從這個數的下一位開始,
    逐個往前移動,直接覆蓋前面的資料,最後輸出的時候記得陣列長度進行相應的減少即可。
  • 如果需要多次刪除的話,那就需要多次重構陣列。
  • 以PTA題目陣列元素的刪除為例:
	scanf("%d", &k);//這裡的k表示刪除的次數;
	for (i = 0; i < k; i++)
	{
		scanf("%d", &order);//order表示想刪除的數的位置;
		for (j = order - 1; j < n; j++)
		{
			array[j] = array[j + 1];
		}
		n--;
	}

1.4 陣列中目前學到的排序方法及其主要思路

1.4.1 選擇排序法:

  • 主要思路:選擇排序法的主要思路是先找出一段範圍內的最值(最大值和最小值都可以),然後將他們先
    放在一邊(習慣上統一先放左邊,所以我們以此方法為例),也就是說找到最值的位置後,讓最值的數的位置
    和最左邊的數的位置進行交換,讓最左邊的空間存放的是最值,然後再在除去左邊的值的剩下的值的範圍中一
    次一次不斷地重複前面的操作直到倒二個數,這是第一層迴圈的終點,第二層迴圈的終點一般都是陣列長度,
    但是它的初值在不斷地從第二個陣列元素的下標開始直到陣列長度停止,最終如果排序完整個陣列的話,往往可
    以得到一個從小到大或者從大到小排列的陣列。其它情況根據具體情況去改變迴圈條件去具體分析。
  • 以PTA的題目選擇法排序為例:
	//資料表達
	unsigned int n;
	int a[11];//陣列a;
	int Index = 0;//控制陣列輸入的下標;
	int count = 0;//計數當前刷過幾遍;
	int temp;//用於儲存暫時的變數;
	int bigIndex;//用來表示更大數的下標;
        //選擇法排序1;
	for (count = 0; count < n - 1; count++)
	{
		bigIndex = count;//表示最大數的下標 並在每一輪先表示那一輪內迴圈的第一個數;
		for (Index = count; Index < n - 1; Index++)
		{
			if (a[bigIndex] < a[Index + 1])//以本迴圈內的第一個數為起始點,不斷與下一個數進行大小比較;
			{
				bigIndex = Index + 1;//用一個下標變數來定位最大的那個數;
			}
			else;
		}
		//將最大數交換到當前的第一個數的位置來,然後把當前第一個數的換到原本最大數的那個位置;
		temp = a[count]; 
		a[count] = a[bigIndex];
		a[bigIndex] = temp;
	}

//細心的讀者會發現,哎呀怎麼給的程式碼和思路中描述的不太一樣,其實他們表達的本質都是一樣的,之所以
會有迴圈條件控制的這兩種不同的寫法,最主要的目的還是為了去避免陣列下標的溢位。

  • 非常非常非常需要注意的一點就是,在陣列問題當中迴圈上下限的設定,不僅僅要滿足邏輯上效果的滿足,更
    重要的是,它還要保障跑的過程中,每一個作為陣列下標的量或表示式值的結果都不能越界!!

    所以我們再放一種寫法它也能過:
	//選擇法排序2;
	for (count = 0; count < n - 1; count++)
	{
		bigIndex = count;//表示最大數的下標再每一輪先表示那一輪內迴圈的第一個數;
		for (Index = count + 1 ; Index < n; Index++)
		{
			if (a[bigIndex] < a[Index])//以本迴圈內的第一個數為起始點,不斷與下一個數進行大小比較;
			{
				bigIndex = Index;//用一個下標變數來定位最大的那個數;
			}
			else;
		}
		//將最大數交換到當前的第一個數的位置來,然後把當前第一個數的換到原本最大數的那個位置;
		temp = a[count]; 
		a[count] = a[bigIndex];
		a[bigIndex] = temp;
	}

1.4.2 氣泡排序法:

  • 實驗思路:氣泡排序法的思路是一種臨近元素兩兩滿足條件不斷交換的思路,同樣設定兩層迴圈,外層迴圈控制
    的範圍是從陣列中的第一個元素開始,不斷得去提取元素,直到提取到最後一個元素,而內層迴圈控制的是每次交換
    的一個範圍,它的每次迴圈的範圍會向一個方向縮減,縮減的數量就是已經排序完成,成功冒泡的元素的個數(常
    見的是往右邊冒泡),然後內迴圈的右界不斷縮減直到為零,而左界保持不變一直都是第一個元素的下標。通過這
    樣的過程,如果最後完全排序完成的話,也可以得到一個從小到大排序或者從大到小排序的陣列,具體情形自己分
    析。
  • 具體的例項程式碼可以參考PTA的題目氣泡排序法:
      //資料表達
	unsigned long int N;
	unsigned long int K;
	int a[101];//陣列a;
	int Index = 0;//控制陣列的下標;
	int count = 0;//計數當前刷過幾遍;
	int temp;//用於儲存暫時的變數;
	//冒泡法排序;
	for (count = 0; count < K ; count++)//這裡表示一共做冒泡法的輪數,K的表達形式與count的初值有關!
	{
		for (Index = 0; Index < N - count-1; Index++)//這裡面的   N - count-1 很重要!!!-1是保證陣列下標不越界;
		{
			if (a[Index] > a[Index + 1])
			{
				temp = a[Index + 1];  a[Index + 1] = a[Index];	a[Index] = temp;//做交換;           
				//要記住交換的    傳遞性   寫法!!
				//這樣寫一是可以的:  temp = a[Index];   a[Index] = a[Index + 1];   a[Index] = temp;
				//記住一個看起來的特點那便是:首 尾 頂 真 !
			}
		}
	}
  • 這裡就分析一下選擇排序法和氣泡排序法的區別:
    **你會發現,選擇排序法的交換是放在第一層迴圈中,而氣泡排序法是放在第二層迴圈中,所以相對來說
    選擇排序法的程式碼的結構性會比氣泡排序法的更好,效率會更高。
  • 更深入的理解請訪問該文章:淺談排序演算法

1.5 陣列做列舉用法及其案例

1.6 雜湊陣列用法及其案例

  • 雜湊陣列的主要思想是用空間換時間,它巧妙地運用了數學中複合函式的思想,正好陣列的下標和它對應的元素
    也在某種程度上反映了一種一一對應的對映關係,所以它讓一個數組去當另外一個數組的下標,讓內陣列對應的元素
    去充當外陣列的下標,不過要求的是,內陣列對應的元素的取值範圍要在外陣列下標的有效範圍之內,這同樣也和數學
    上覆合函式的對應思路一致。
  • 以PTA中有重複的資料I為例:
//這是過不了審的用了迴圈巢狀的做法:
int main()
{
	//資料表達
	int n, i, k;
	int numbers[100000];
	int numbers1[100000];
	int count = 0;
	//流程設計
	//input
	scanf("%d", &n);
	for (i = 0; i < n; i++)
	{
		scanf("%d", &numbers[i]);
	}
	
	for (i = 0; i < n; i++)
	{
		for (k = i; k < n; k++)
		{
			if (numbers[i] == numbers[k])
			{
				count++;
			}
		}
	}

	if (count >= 2)
	{
		printf("YES");
	}
	else
	{
		printf("NO");
	}

	return 0;
}
/* 用這種方法來解決  有重複的資料I 過不了數字很大的 測試點。但是這個方法是有值得學習的地方的
那就是對陣列的一種思考方式:==那就是可以通過定義兩個在改變的不同變數來當作同一陣列的下標使用
陣列。== */
  • 其實可以把陣列想象成數學中的函式關係,下標就是自變數,支援 複合函式 的思想 所以也就支援陣列巢狀。
//於是有了雜湊陣列的方法:
int main()
{
	//資料表達
	int n, i;
	int numbers[100000];//內陣列用來存放實際元素;
	static int numbers1[100001];//外陣列用來統計個數。
	int flag = 1;
	//流程設計
	scanf("%d", &n);
	for (i = 0; i < n; i++)
	{
		scanf("%d", &numbers[i]);
	}

	for (i = 0; i < n; i++)
	{
		numbers1[numbers[i]]++;
	}

	for (i = 0; i < n; i++)
	{
		if (numbers1[numbers[i]] >= 2)
		{
			flag = 0;
		}
	}

	if (flag)
	{
		printf("NO");
	}
	else
	{
		printf("YES");
	}

	return 0;
}
  • 值得注意的是使用了雜湊陣列之後,後期對外陣列計數的統計,你所使用的下標也應該
    是陣列下標,這樣才能夠既解決計數統計的需要又不至於要遍歷整個外陣列,浪費時間。
  • 要注意外陣列的長度和內陣列元素資料取值範圍的一一對應,避免下標越界!

1.7 字元陣列、字串特點及程式設計注意事項

1.7.1 字元陣列的輸入:

  • scanf型別的輸入方法:支援中間沒有空格的輸入型別,因為一遇到空格或者回車就會立刻
    停止輸入。另外這種方法會自動補充字元陣列的結束標誌,不需要另外自己賦值。
      //假設此刻有一個字元陣列為a
      scanf("%s",a);
      //其中字元陣列的變數名本身就代表首地址所以不需要 & ,其次不需要[]。
  • while型別的輸入:這種做法就像是把字元陣列拆分成一個一個的字元,它是相當於在迴圈中
    一個一個把字元給輸入到字元陣列當中,可以應對有空格或者回車的輸入環境,但是缺點是,它
    並不會自動補充字元陣列的結束符號 '\0' (也就是 0 );所以往往需要在迴圈結束時在迴圈外
    對陣列的已輸入元素的後一位手動賦值來封尾,這樣,字元陣列的輸入才算成功輸入。另外,輸
    入迴圈結束的條件往往需要自己設定,這個根據題目來具體分析。
      //這裡假設輸入一串字元並用 回車來結束輸入:
      while (charray[i] != '\n')

2. PTA實驗作業(7分)

2.1 題目名1(3分)

選擇一題一維陣列相關題目。請認真寫虛擬碼整理解題思路。自己程式碼和同學程式碼比較,說明各自程式碼特點。

2.1.1 虛擬碼

用程式碼渲染符號```渲染虛擬碼。注意:虛擬碼不是翻譯程式碼,必須是程式碼+中文文字描述。
資料處理可以用C語言符號介紹。具體參考看課件!!!

2.1.2 程式碼截圖

貼圖展示程式碼,不要複製。

2.1.3 找一份同學程式碼(儘量找思路和自己差距較大同學程式碼)比較,說明各自程式碼特點。

2.2 題目名2(2分)

選擇閱覽室或鞍點這2題介紹二維陣列。並說明和超星視訊做法區別。

2.2.1 虛擬碼

2.2.2 程式碼截圖

2.2.3 請說明和超星視訊做法區別,各自優缺點。

2.3 題目名3(2分)

選擇切分表示式這題介紹字元陣列。並說明和超星視訊做法區別。

2.3.1 虛擬碼

2.3.2 程式碼截圖

2.3.3 請說明和超星視訊做法區別,各自優缺點。