2018年物聯網學生科協軟體第二次培訓總結
2018年物聯網學生科協軟體第二次培訓總結
文章目錄
一、陣列----多資料儲存
1. 陣列的定義
陣列是c語言中的一種複合資料型別,是相同資料型別的有序集合。
2. 陣列的宣告
資料型別 陣列名[下標個數];
int array[100];
double d_array[30];
3. 陣列的初始化
(1).
int arr1[3] = {1, 2, 3};
int arr2[] = {1, 2, 3}; //在這裡,我們arr[3]裡邊的數字可以不用寫
(2).
int arr2[3] = {1, 2}; //也是可以的,注意最後一個數初始化為0
(3).
int arr3[3] = {1, 2, 3, 4}; //錯誤,不能超過陣列長度
4. 陣列中元素的訪問
通過陣列下標來訪問每個元素
int a[5]={1,2,3,4,5};
a[0]=1; //a[0]為陣列中的首個元素
a[1]=2;
a[2]=3;
a[3]=4;
a[4]=5;
小程式碼示例:
int score[10]; //儲存10個整型值的陣列
int count = 10; //學生人數
printf("Enter the 10 scores: \n");
for(int i=0; i< count; i++)
{
scanf(“%d”, &score[i]); //從鍵盤讀入一個分數並存到數組裡
}
5.陣列的記憶體分配
int a[100];
double b[30];
printf("%d\n",sizeof(a)); //400
printf("%d",sizeof(b)); //240
當編譯器對以上程式碼進行編譯時,就會為陣列分配記憶體單元。 假設計算機指定陣列score中的元素從地址為1000的地方開始存放。
具體分配原理如下圖所示:
二、數值交換問題
1. 最常用的方法----建立臨時變數
小程式碼示例:
int a=10,b=20,temp;
temp = a;
a = b;
b = temp;
printf("%d%d", a,b);
2. 數學計算的方法
小程式碼示例:
int a =10, b = 20;
a = a - b;
b = a + b;
a = b - a;
printf("%d%d", a, b);
缺點:兩個數的和可能會越界,適用於兩個比較小的數
3. 異或運算的方法
小程式碼示例:
int a =10, b = 20;
a = a^b;
b = a^b;
a = a^b;
printf("%d%d", a, b);
思路:將a,b轉換為二進位制數(10 = 01010,20 = 10010)
按位異或(兩個值相同為0,不同為1)
4. 陣列換標不換值的方法
小程式碼示例:
int a=10,b=20;
int array1[2] = {10,20}; //存a、b
int array2[2] = {0,1}; //存下標
b = array1[array2[0]];
a = array1[array2[1]];
printf("%d%d",a,b);
思路:用陣列元素作為陣列的下標,這種方法換邏輯不換儲存
三、 基本的排序演算法
1. 氣泡排序(升序)
基本操作:比較陣列中相鄰的元素。如果這個數比它後一個大,就交換它們兩個。
第一步:從陣列第一和第二個元素(第一對)開始,執行基本操作,直到陣列末尾的兩個元素(最後一對)。這樣執行一遍後,最後的元素會是陣列中最大的數。
第二步:重複基本操作,但每次操作的元素會少一個(因為執行完n次操作後,前n個最大的元素會被排好序),直到沒有任何一對數字需要比較。氣泡排序完成。
小程式碼示例:
#include<stdio.h>
int main(){
int a[5] = {2,3,4,1,6};
int i, j, temp;
for (j = 0; j < 4; j++)
for (i = 0; i < 4 - j; i++){
if(a[i] > a[i + 1]){
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
for(j = 0; j < 5; j++){
printf("%d ",a[j]);
}
return 0;
}
2. 選擇排序(升序)
基本操作:每次找出操作序列中最小的數放到最前面。
第一步:第一次操作遍歷整個序列,將最小的元素放到首位。
第二步:重複基本操作,第n次操作從序列第n個元素開始遍歷序列,將最小的元素放到序列第n個位置。直到某次操作序列中沒有元素可以遍歷。選擇排序完成。
圖解如下:
小程式碼示例:
#include<stdio.h>
int main(){
int a[5] = {2,3,4,1,6};
int i, j, temp;
//每一次都找出最小的放到前面
for(i = 0; i < 4; i++)
{
min = i; //查詢最小值的下標
for(j = i+1; j < 5; j++)
if(a[min] > a[j])
min = j; //交換最小值的下標
//判斷一下最小的是不是自身,如果不是則交換位置
if(min != i)
{
temp = a[min];
a[min] = a[i];
a[i] = temp;
}
}
for(i=0;i<5;i++){
printf("%d",a[i]);
}
}
3. 插入排序(升序)
基本操作:將有序序列的後一個元素插入到序列當中,使其依然有序。
第一步:假設初始時有序序列中只有第一個元素,此時執行基本操作,會將第二個元素排好序。此時有序序列中有兩個元素。
第二步:重複基本操作,有序序列的長度不斷增加。當有序序列中的元素個數和原序列相等時,即所有元素均有序排列時,插入排序完成。
圖解如下:
小程式碼示例:
#include<stdio.h>
int main(){
int i, j, temp;
int a[5] = {2,3,4,1,6};
for(i = 1 ;i < 5 ; i++){
temp = a[i];
for(j = i ; j>0 && a[j-1]>temp ; j--)
a[j] = a[j-1];
a[j]=temp;
}
for(i=0;i<5;i++){
printf("%d",a[i]);
}
return 0;
}
四、 字元與字串
1. 字元的概念
字元型資料包括 字元常量 和 字元變數。
(1). 字元常量:
- 概念 :
是單引號括起來的一個字元。例如:‘a’、‘b’、‘=’、‘?’都是合法的字元常量。 - 特點 :
①字元常量只能用單引號括起來,不能用雙引號或者其他字元;
②字元常量只能是單個字元,不能是字串;
③字元可以是字符集中的任意字元,但數字被定義為字元型之後不能參與數值的運算。(比如:‘3’和3) - 特殊的字元常量:
在上次培訓我們提到的轉義字元是一種特殊的字元常量,其具有特定的含義不同於字元原有的意義即為”轉義”。
(2). 字元變數:
- 字元型變數用來儲存字元資料,即單個字元。
- 字元變數的型別說明符是char。
注意: ①每個字元變數被分配一個位元組的記憶體空間,因此只能存放一個字元;
程式碼小示例:
char a='h';
printf("%d",sizeof(a)); //1
字元值是以ASCII碼的形式存放在變數的記憶體單元之中的。
2. 字元的輸入與輸出
char ch;
scanf(“%c”,&ch);
printf(“%c”,ch);
小練習: 輸入一個字母,將其大寫轉小寫,小寫轉大寫。
小程式碼示例:
#include<stdio.h>
int main(){
char a;
scanf("%c",&a);
if(a>=65&&a<=90)
a += 32;
else if(a>=97&&a<=122)
a -= 32;
printf("%c",a);
return 0;
}
3. 字串的概念
從形式上看,一個字串就是用一對雙引號括起來的一串字元,其雙引號是該字串的起,止標誌符,它不屬於字串本身的字元。
例:
“string”
“物聯網院學生科協”
4. 字串的初始化
字元型陣列表示字串
char[]=“iotesta”
char b[20]=“I love esta”
Char str[6]={‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\0’}
注意: 在進行逐個元素初始化時,必須明確寫出字串結束符’\0’
5. 字串的輸入與輸出
scanf(“%s”,str); //(注意!不用寫&)
printf(“%s”,str);
小練習:輸入一個字串,將其大寫轉小寫,小寫轉大寫。
小程式碼示例:
#include<stdio.h>
int main(){
int i;
char a[12]="iLoVEesTA";
for(i=0;i<12;i++){
if(a[i]>=65&&a[i]<=90)
a[i] += 32;
else if(a[i]>=97&&a[i]<=122)
a[i] -= 32;
}
printf("%s",a);
return 0;
}
6. 關於字串的常用函式
函式:函式是一個封裝一個功能的程式碼塊,便於重複使用。主要是傳入引數,獲得返回值,或者在函式內對引數進行操作。其中關於字串的常用函式都在<string.h>標頭檔案裡,即在使用時要在最上面加上 #include<string.h>
(1). 求字串長度----strlen函式
int strlen (const char s[ ]);
①功能:計算字串的長度
②返回值:返回字串的實際長度,不包括‘\0’在內
③注意:在求字串長度的過程中,遇到字串‘\0’就結束,只計算起始位置到‘\0’前面的字元個數,例如:strlen(“AB\0CD\0EF”)的結果是2
sizeof()與strlen()函式的區別:
sizeof()計算的是系統為變數分配的記憶體空間的大小,會加上隱藏結束符的長度。
(2). 字串拷貝
- strcpy函式
char* strcpy (char *s1, const char *s2);
①功能:將字串s2複製到s1指定的地址(即將字串s2拷貝到s1中去)
②返回值:字串s1的首地址。
③注意:字串s1必須是陣列或者已經分配空間的字元型指標,並且空間足夠大,該函式不分配空間;拷貝時‘\0’一同被拷貝;不能使用賦值語句給一個字元陣列賦值;
- strncpy函式
char* strncpy (char *s1, const char *s2, int n);
功能:將s2的前n個字元複製到s1中對應的地址, 並在末尾加‘\0’ ;
(3). 字串連線----strcat函式
char* strcat (char *s1, const char *s2);
①功能:將字元陣列s2連線到字元陣列s1尾部
②說明:字元陣列s1必須空間足夠大(s1的儲存空間≥strlen(s1)+strlen(s2)+1),連線前,兩串均以‘\0’結束,連線後,串s1原來的‘\0’被覆蓋,新得到的字串最後加‘\0’;呼叫此函式後,s1的長度等於s1、s2兩個字串長度之和。
小程式碼示例:
char a[20]="Hello"; //字串長度為5
char b[ ]="World"; //字串長度為5
strcat(a," "); //連線一個空格到a串之後
strcat(a,b); //把b串連線到a串之後
printf("%s %d",a,strlen(a));
//執行該程式的輸出結果是: Hello World 11
(4). 字串比較----strcmp函式
int strcmp (const char *s1, const char *s2);
①功能:比較字串s1和s2。
②比較規則:對兩個串從左向右逐個字元比較(ASCII碼),直到遇到不同的字元或者‘\0’為止;
③返回值:返回int型整數。
(1)若s1 < s2,返回負整數;
(2)若s1 > s2,返回正整數;
(3)若s1 = s2,返回零;
注意: 字串比較不能用“==”,必須用strcmp;
以上函式的綜合使用
小程式碼示例:
char str1[10];
char str2[10];
scanf("%s%s",str1,str2);
//求字串的長度
printf("%d %d\n",strlen(str1),strlen(str2));
//字串連線
strcat(str1,str2);
printf("%s\n",str1);
//字串拷貝
strcpy(str1,str2);
printf("%s\n",str1);
//字串比較
printf("%d\n",strcmp(str1,str2));
五、有趣的小演算法
貪心演算法
貪心演算法(又稱貪婪演算法)是指,在對問題求解時,總是做出在當前看來最好的選擇。也就是說,將整體最優問題分解為區域性來考慮,做出的是在某種意義上的區域性最優解。
貪心選擇 — 第一個基本要素
貪心選擇是指,所求問題的整體最優解可以通過一系列區域性最優的選擇來達到。
對於一個具體問題,要確定它是否具有貪心選擇的性質,我們必須證明每一步所作的貪心選擇最終能得到問題的最優解。通常可以首先證明問題的一個整體最優解,是從貪心選擇開始的,而且作了貪心選擇後,原問題簡化為一個規模更小的類似子問題。
- 貪心演算法相關經典問題:
貨幣選擇問題、揹包問題、區間排程問題、字典序最小問題
小練習: 雙11已經不遠了,但一橙小萌新很苦惱,因為他每個月的15號才能收到生活費。為了解決這個問題,他決定提前向媽媽索要11月份的生活費,但他的媽媽卻沒有那麼容易將錢給他。媽媽說:你不是在學程式設計嗎?那你告訴我,如果接下來幾個月的生活費我都不用移動支付的方式,而是以紙幣的形式給你,我最少要準備多少張人民幣呢?你回答出來就提前給你11月份的生活費,否則你雙11就別買東西了!
一橙小萌新想買的羅技滑鼠在購物車裡很久了,要是錯過雙11就太悲傷了,你們快幫幫他吧!(假設每個月的生活費是整數。人民幣一共有100元、50元、10元、5元、2元和1元六種)。
Input
輸入資料第1行是一個整數n(n<100),表示接下來的n個月,第2到第n+1行每行一個數,表示每個月一橙小萌新的生活費。
Output
輸出一個整數x,表示至少需要準備的人民幣張數。每個輸出佔一行。
Sample Input
3 1 2 3
Sample Output
4
小程式碼示例:
while(scanf("%d",&n)!=EOF&&n!=0)
{
sum=0;
for(i=0; i<n; i++)
{
scanf("%d",&m);
sum+=m/100;
m%=100;
sum+=m/50;
m%=50;
sum+=m/10;
m%=10;
sum+=m/5;
m%=5;
sum+=m/2;
m%=2;
sum+=m;
}
printf("%d\n",sum);
}
思路:從大面值鈔票往下選,便是最少的張數。
貪心演算法不是對所有問題都能得到整體最優解,關鍵是貪心策略的選擇,選擇的貪心策略必須具備無後效性,即某個狀態以前的過程不會影響以後的狀態,只與當前狀態有關。