程序設(shè)計(jì)與算法(一) 第十周

結(jié)構(gòu)(struct)

現(xiàn)實(shí)需求

  • 在現(xiàn)實(shí)問題中剔氏,常常需要用一組不同類型的數(shù)據(jù)來描述一個(gè)事物塑猖。比如一個(gè)
    學(xué)生的學(xué)號(hào)、姓名和績點(diǎn)谈跛。一個(gè)工人的姓名羊苟、性別、年齡感憾、工資蜡励、電話......

  • 如果編程時(shí)要用多個(gè)不同類型的變量來描述一個(gè)事物,就很麻煩阻桅。當(dāng)然希望
    只用一個(gè)變量就能代表一個(gè)“學(xué)生”這樣的事物凉倚。

  • C++允許程序員自己定義新的數(shù)據(jù)類型。因此針對(duì)“學(xué)生”這種事物鳍刷,可以
    定義一種新名為Student的數(shù)據(jù)類型占遥,一個(gè)Student類型的變量就能描述一個(gè)學(xué)
    生的全部信息。同理输瓜,還可以定義數(shù)據(jù)類型 Worker以表示工人瓦胎。

  • 用“struct”關(guān)鍵字來定義一個(gè)“結(jié)構(gòu)”,也就定義了一個(gè)新的數(shù)據(jù)類型:

struct 結(jié)構(gòu)名
{
類型名 成員變量名尤揣;
類型名 成員變量名搔啊;
類型名 成員變量名;
……
};

struct Student {
unsigned ID;
char szName[20];
float fGPA;
};

Student 即成為自定義類型的名字北戏,可以用來定義變量

Stuent s1,s2; 
  • 例兩個(gè)同類型的結(jié)構(gòu)變量负芋,可以互相賦值。但是結(jié)構(gòu)變量之間不能用
    “==”嗜愈、“!=”旧蛾、“<”、“>”蠕嫁、“<=”锨天、“>=”進(jìn)行比較運(yùn)算。

  • 一般來說剃毒,一個(gè)結(jié)構(gòu)變量所占的內(nèi)存空間的大小病袄,就是結(jié)構(gòu)中所有成員變
    量大小之和搂赋。結(jié)構(gòu)變量中的各個(gè)成員變量在內(nèi)存中一般是連續(xù)存放的,

  • 一個(gè)結(jié)構(gòu)的成員變量可以是任何類型的益缠,包括可以是另一個(gè)結(jié)構(gòu)類型:

struct Date {
int year;
int month;
int day;
};
struct StudentEx {
unsigned ID;
char szName[20];
float fGPA;
Date birthday;
};

  • 結(jié)構(gòu)的成員變量可以是指向本結(jié)構(gòu)類型的變量的指針
struct Employee {
  string name;
  int age;
  int salary;
  Employee * next;
};

訪問結(jié)構(gòu)變量的成員變量

  • 一個(gè)結(jié)構(gòu)變量的成員變量脑奠,可以完全和一個(gè)普通變量一樣來使用,也可以
    取得其地址幅慌。使用形式:
    結(jié)構(gòu)變量名.成員變量名
struct Date {
  int year;
  int month;
  int day;
};
struct StudentEx {
  unsigned ID;
  char szName[20];
  float fGPA;
  Date birthday;
};

StudentEx stu;
cin >> stu.fGPA;
stu.ID = 12345;
strcpy(stu.szName, "Tom");
cout << stu.fGPA;
stu.birthday.year = 1984;
unsigned int * p = & stu.ID; //p指向stu中的ID成員變量

結(jié)構(gòu)變量的初始化

  • 結(jié)構(gòu)變量可以在定義時(shí)進(jìn)行初始化:
    StudentEx stu = { 1234,"Tom",3.78,{ 1984,12,28 }};

結(jié)構(gòu)數(shù)組

StudentEx MyClass [50];

StudentEx MyClass2[50] = {
  { 1234,"Tom",3.78,{ 1984,12,28 }},
  { 1235,"Jack",3.25,{ 1985,12,23 }},
  { 1236,"Mary",4.00,{ 1984,12,21 }},
  { 1237,"Jone",2.78,{ 1985,2,28 }}
};

MyClass[1].ID = 1267;
MyClass[2].birthday.year = 1986;
int n = MyClass[2].birthday.month;
cin >> MyClass[0].szName;

指向結(jié)構(gòu)變量的指針

  • 定義指向結(jié)構(gòu)變量的指針
    結(jié)構(gòu)名 * 指針變量名;
StudentEx * pStudent;
StudentEx Stu1;
pStudent = & Stu1;
StudentEx Stu2 = * pStudent; 

指向結(jié)構(gòu)變量的指針

  • 通過指針宋欺,訪問其指向的結(jié)構(gòu)變量的成員變量:
    指針->成員變量名
    或:
    (* 指針).成員變量名
StudentEx Stu;
StudentEx * pStu;
pStu = & Stu;
pStu->ID = 12345;
(*pStu).fGPA = 3.48;
cout << Stu.ID << endl; //輸出 12345
cout << Stu.fGPA << endl; //輸出 3.48

C++程序結(jié)構(gòu)

全局變量和局部變量

  • 定義在函數(shù)內(nèi)部的變量叫局部變量(函數(shù)的形參也是局部變量)
  • 定義在所有函數(shù)的外面的變量叫全局變量
  • 全局變量在所有函數(shù)中均可以使用,局部變量只能在定義它的函數(shù)內(nèi)部使用
#include <iostream>
using namespace std;
int n1 = 5, n2 = 10; //全局變量
void Function1() {
  int n3 =4;
  n2 = 3;
}
void Function2() {
  int n4;
  n1 = 4;
  n3 = 5; //編譯出錯(cuò)欠痴,n3無定義
}

靜態(tài)變量

  • 全局變量都是靜態(tài)變量迄靠。局部變量定義時(shí)如果前面加了“static”關(guān)鍵字,
    則該變量也成為靜態(tài)變量
  • 靜態(tài)變量的存放地址喇辽,在整個(gè)程序運(yùn)行期間掌挚,都是固定不變的
  • 非靜態(tài)變量(一定是局部變量)地址每次函數(shù)調(diào)用時(shí)都可能不同,在函數(shù)的一次
    執(zhí)行期間不變
  • 如果未明確初始化,則靜態(tài)變量會(huì)被自動(dòng)初始化成全0(每個(gè)bit都是0)菩咨,局
    部非靜態(tài)變量的值則隨機(jī)

靜態(tài)變量示例

#include <iostream>
using namespace std;
void Func()
{
  static int n = 4; //靜態(tài)變量只初始化一次
  cout << n << endl;
  ++ n;
}
int main()
{
  Func(); Func(); Func();
}
輸出結(jié)果:
4
5
6

靜態(tài)變量應(yīng)用:strtok的實(shí)現(xiàn)

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
  char str[] ="- This, a sample string, OK.";
  //下面要從str逐個(gè)抽取出被" ,.-"這幾個(gè)字符分隔的字串
  char * p = strtok (str," ,.-");
  while ( p != NULL) //只要p不為NULL吠式,就說明找到了一個(gè)子串
{
    cout << p << endl;
    p = strtok(NULL, " ,.-");
    //后續(xù)調(diào)用,第一個(gè)參數(shù)必須是NULL
}
  return 0;
}
char * p = strtok (str," ,.-");
while ( p != NULL) //只要p不為NULL抽米,就說明找到了一個(gè)子串
{
  cout << p << endl;
  p = strtok(NULL, " ,.-");
//后續(xù)調(diào)用特占,第一個(gè)參數(shù)必須是NULL
}
輸出結(jié)果:
This
a
sample
string
OK

-?This,?a?sample?string,?OK\0
char * Strtok(char * p,char * sep)
{
  static char * start ; //本次查找子串的起點(diǎn)
  if(p)
  start = p;
  for(; *start && strchr(sep,*start); ++ start); //跳過分隔符號(hào)
  if( * start == 0)
  return NULL;
  char * q = start;
  for(; *start && !strchr(sep,*start); ++ start); //跳過非分隔符號(hào)
  if( * start) {
  * start = 0;
  ++ start;
}
  return q;
}

標(biāo)識(shí)符的作用域

  • 變量名、函數(shù)名云茸、類型名統(tǒng)稱為“標(biāo)識(shí)符”是目。一個(gè)標(biāo)識(shí)符能夠起作用的范圍
    ,叫做該標(biāo)識(shí)符的作用域
  • 在一個(gè)標(biāo)識(shí)符的作用域之外使用該標(biāo)識(shí)符标捺,會(huì)導(dǎo)致“標(biāo)識(shí)符沒有定義”的編
    譯錯(cuò)誤懊纳。使用標(biāo)識(shí)符的語句,必須出現(xiàn)在它們的聲明或定義之后
  • 在單文件的程序中亡容,結(jié)構(gòu)嗤疯、函數(shù)和全局變量的作用域是其定義所在的整個(gè)文
  • 函數(shù)形參的作用域是整個(gè)函數(shù)
  • 局部變量的作用域,是從定義它的語句開始闺兢,到包含它的最內(nèi)層的那一對(duì)大
    括號(hào)“{}”的右大括號(hào) “}”為止
  • for循環(huán)里定義的循環(huán)控制變量茂缚,其作用域就是整個(gè)for循環(huán)
  • 同名標(biāo)示符的作用域,可能一個(gè)被另一個(gè)包含屋谭。則在小的作用域里脚囊,作用域
    大的那個(gè)標(biāo)識(shí)符被屏蔽,不起作用桐磁。
void Func(int m)
{
  for( int i = 0; i < 4;++i ) {
    if( m <= 0 ) {
      int k = 3;
      m = m *( k ++ );
  }
  else {
    k = 0; //編譯出錯(cuò)悔耘,k無定義
    int m = 4;
    cout << m;
  }
}
i= 2; //編譯出錯(cuò),i無定義
}

變量的生存期

  • 所謂變量的“生存期”所意,指的是在此期間淮逊,變量占有內(nèi)存空間,其占有的內(nèi)
    存空間只能歸它使用扶踊,不會(huì)被用來存放別的東西泄鹏。
  • 而變量的生存期終止,就意味著該變量不再占有內(nèi)存空間秧耗,它原來占有的內(nèi)
    存空間备籽,隨時(shí)可能被派做他用。
  • 全局變量的生存期分井,從程序被裝入內(nèi)存開始车猬,到整個(gè)程序結(jié)束。
  • 靜態(tài)局部變量的生存期尺锚,從定義它語句第一次被執(zhí)行開始珠闰,到整個(gè)程序結(jié)束
    為止。
  • 函數(shù)形參的生存期從函數(shù)執(zhí)行開始瘫辩,到函數(shù)返回時(shí)結(jié)束伏嗜。非靜態(tài)局部變量的
    生存期,從執(zhí)行到定義它的語句開始伐厌,一旦程序執(zhí)行到了它的作用域之外承绸,其
    生存期即告終止。
void Func(int m)
{
  for( int i = 0; i < 4;++i ) {
    if( m <= 0 ) {
      int k = 3;
      m = m *( k ++ );
    }
    else {
      k = 0; //編譯出錯(cuò)挣轨,k無定義
      int m = 4;
      cout << m;
    }
  }
i= 2; //編譯出錯(cuò)军熏,i無定義
}

簡單排序

排序問題

  • 例題: 編程接收鍵盤輸入的若干個(gè)整數(shù),排序后從小到大輸出卷扮。先輸入一個(gè)
    整數(shù)n荡澎,表明有n個(gè)整數(shù)需要排序,接下來再輸入待排序的n個(gè)整數(shù)画饥。

解題思路:先將n個(gè)整數(shù)輸入到一個(gè)數(shù)組中衔瓮,然后對(duì)該數(shù)組進(jìn)行排序,最后遍
歷整個(gè)數(shù)組抖甘,逐個(gè)輸出其元素热鞍。
對(duì)數(shù)組排序有很多種簡單方法,如“冒泡排序”衔彻、 “選擇排序”薇宠、 “插入排
序”等

選擇排序

如果有N個(gè)元素需要排序,那么首先從N個(gè)元素中找到最小的那個(gè)(稱為第0
小的)放在第0個(gè)位子上(和原來的第0個(gè)位子上的元素交換位置)艰额,然后再從剩
下的N-1個(gè)元素中找到最小的放在第1個(gè)位子上澄港,然后再從剩下的N-2個(gè)元素中
找到最小的放在第2個(gè)位子上……直到所有的元素都就位。

void SelectionSort(int a[] ,int size)
{
  for( int i = 0; i < size - 1; ++i ){//每次循環(huán)后將第i小的元素放好
    int tmpMin = i;
    //用來記錄從第i個(gè)到第size-1個(gè)元素中柄沮,最小的那個(gè)元素的下標(biāo)
      for( int j = i+1; j < size ; ++j) {
        if( a[j] < a[tmpMin] )
          tmpMin = j;
      }
//下面將第i小的元素放在第i個(gè)位子上回梧,并將原來占著第i個(gè)位子的元素挪到后面
    int tmp = a[i];
    a[i] = a[tmpMin];
    a[tmpMin] = tmp;
    }
}

插入排序

  • 將整個(gè)數(shù)組a分為有序的部分和無序的兩個(gè)部分废岂。前者在左邊,后者在右邊狱意。
  • 開始有序的部分只有a[0]湖苞,其余都屬于無序的部分
  • 每次取出無序部分的第一個(gè)(最左邊)元素,把它加入到有序部分详囤。假設(shè)插
    入到合適位置p, 則原p位置及其后面的有序部分元素财骨,都向右移動(dòng)一個(gè)位子。
    有序的部分即增加了一個(gè)元素藏姐。
  • 直到無序的部分沒有元素
void InsertionSort(int a[] ,int size)
{
for(int i = 1;i < size; ++i ) {
//a[i]是最左的無序元素隆箩,每次循環(huán)將a[i]放到合適位置
for(int j = 0; j < i; ++j)
if( a[j]>a[i]) {
//要把a(bǔ)[i]放到位置j,原下標(biāo)j到 i-1的元素都往后移一個(gè)位子
int tmp = a[i];
for(int k = i; k > j; --k)
a[k] = a[k-1];
a[j] = tmp;
break;
}
}
}

冒泡排序

  • 將整個(gè)數(shù)組a分為有序的部分和無序的兩個(gè)部分羔杨。前者在右捌臊,后者在左邊。
  • 開始兜材,整個(gè)數(shù)組都是無序的娃属。有序的部分沒有元素。
  • 每次要使得無序部分最大的元素移動(dòng)到有序部分第一個(gè)元素的左邊护姆。移動(dòng)的
    方法是:依次比較相鄰的兩個(gè)元素矾端,如果前面的比后面的大,就交換他們的位
    置卵皂。這樣秩铆,大的元素就像水里氣泡一樣不斷往上浮。移動(dòng)結(jié)束有序部分增加了
    一個(gè)元素灯变。
  • 直到無序的部分沒有元素
void BubbleSort(int a[] ,int size)
{
for(int i = size-1;i > 0; --i ) {
 //每次要將未排序部分的最大值移動(dòng)到下標(biāo)i的位置
for(int j = 0; j < i; ++j) //依次比較相鄰的兩個(gè)元素
if( a[j] > a[j+1]) {
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
}
}
}

簡單排序的效率

  • 上面3種簡單排序算法殴玛,都要做 n^2量級(jí)次數(shù)的比較(n是元素個(gè)數(shù))!
  • 好的排序算法添祸,如快速排序滚粟,歸并排序等,只需要做n*log2(n)量級(jí)次數(shù)的比
    較!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市刃泌,隨后出現(xiàn)的幾起案子凡壤,更是在濱河造成了極大的恐慌,老刑警劉巖耙替,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件亚侠,死亡現(xiàn)場離奇詭異,居然都是意外死亡俗扇,警方通過查閱死者的電腦和手機(jī)硝烂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铜幽,“玉大人滞谢,你說我怎么就攤上這事串稀。” “怎么了狮杨?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵厨诸,是天一觀的道長。 經(jīng)常有香客問我禾酱,道長,這世上最難降的妖魔是什么绘趋? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任颤陶,我火速辦了婚禮,結(jié)果婚禮上陷遮,老公的妹妹穿的比我還像新娘滓走。我一直安慰自己,他們只是感情好帽馋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布搅方。 她就那樣靜靜地躺著,像睡著了一般绽族。 火紅的嫁衣襯著肌膚如雪姨涡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天吧慢,我揣著相機(jī)與錄音涛漂,去河邊找鬼。 笑死检诗,一個(gè)胖子當(dāng)著我的面吹牛匈仗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逢慌,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼悠轩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了攻泼?” 一聲冷哼從身側(cè)響起火架,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎忙菠,沒想到半個(gè)月后距潘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡只搁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年音比,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氢惋。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡洞翩,死狀恐怖稽犁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情骚亿,我是刑警寧澤已亥,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站来屠,受9級(jí)特大地震影響虑椎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜俱笛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一捆姜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迎膜,春花似錦泥技、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至榕订,卻和暖如春店茶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背劫恒。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工忽妒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兼贸。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓段直,卻偏偏與公主長得像,于是被迫代替她去往敵國和親溶诞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鸯檬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法螺垢,內(nèi)部類的語法喧务,繼承相關(guān)的語法,異常的語法枉圃,線程的語...
    子非魚_t_閱讀 31,625評(píng)論 18 399
  • 1. 結(jié)構(gòu)體和共同體的區(qū)別功茴。 定義: 結(jié)構(gòu)體struct:把不同類型的數(shù)據(jù)組合成一個(gè)整體,自定義類型孽亲。共同體uni...
    breakfy閱讀 2,124評(píng)論 0 22
  • 概述 排序有內(nèi)部排序和外部排序坎穿,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    蟻前閱讀 5,183評(píng)論 0 52
  • 路過廠區(qū)的綠化帶玲昧,感覺被一種熟悉又久違的氣息牽引著栖茉。停住腳步,環(huán)顧四周孵延,在那一邊濃郁中吕漂,找尋了你,不張揚(yáng)的淡黃尘应,隱...
    云兒朵朵飄閱讀 887評(píng)論 0 1
  • 中國傳媒大學(xué)是211院校惶凝,該校有兩個(gè)學(xué)院招收漢語國際教育碩士專業(yè)考生,分別為文學(xué)院和漢語國際教育中心犬钢,在此請報(bào)考該...
    mtcsol閱讀 335評(píng)論 0 0