1、不用中間變量,用兩種方法交換A和B的值
// 1.中間變量
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
// 2.加法
void swap(int a, int b) {
a = a + b;
b = a - b;
a = a - b;
}
// 3.異或(相同爲0,不同爲1. 可以理解爲不進位加法)
void swap(int a, int b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
2、求最大公約數
/** 1.直接遍歷法 */
int maxCommonDivisor(int a, int b) {
int max = 0;
for (int i = 1; i <=b; i++) {
if (a % i == 0 && b % i == 0) {
max = i;
}
}
return max;
}
/** 2.輾轉相除法 */
int maxCommonDivisor(int a, int b) {
int r;
while(a % b > 0) {
r = a % b;
a = b;
b = r;
}
return b;
}
// 擴展:最小公倍數 = (a * b)/最大公約數
3、模擬棧操作
- 棧是一種數據結構,特點:先進後出
- 練習:使用全局變量模擬棧的操作
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
//保護全局變量:在全局變量前加static後,這個全局變量就只能在本文件中使用
static int data[1024];//棧最多能保存1024個數據
static int count = 0;//目前已經放了多少個數(相當於棧頂位置)
//數據入棧 push
void push(int x){
assert(!full());//防止數組越界
data[count++] = x;
}
//數據出棧 pop
int pop(){
assert(!empty());
return data[--count];
}
//查看棧頂元素 top
int top(){
assert(!empty());
return data[count-1];
}
//查詢棧滿 full
bool full() {
if(count >= 1024) {
return 1;
}
return 0;
}
//查詢棧空 empty
bool empty() {
if(count <= 0) {
return 1;
}
return 0;
}
int main(){
//入棧
for (int i = 1; i <= 10; i++) {
push(i);
}
//出棧
while(!empty()){
printf("%d ", top()); //棧頂元素
pop(); //出棧
}
printf("\n");
return 0;
}
4、排序算法
選擇排序、冒泡排序、插入排序三種排序算法可以總結爲如下:
都將數組分爲已排序部分和未排序部分。
1.選擇排序將已排序部分定義在左端,然後選擇未排序部分的最小元素和未排序部分的第一個元素交換。
2.冒泡排序將已排序部分定義在右端,在遍歷未排序部分的過程執行交換,將最大元素交換到最右端。
3.插入排序將已排序部分定義在左端,將未排序部分元的第一個元素插入到已排序部分合適的位置。
4.1、選擇排序
- 【選擇排序】:最值出現在起始端
- 第1趟:在n個數中找到最小(大)數與第一個數交換位置
- 第2趟:在剩下n-1個數中找到最小(大)數與第二個數交換位置
- 重複這樣的操作...依次與第三個、第四個...數交換位置
-
第n-1趟,最終可實現數據的升序(降序)排列。
void selectSort(int *arr, int length) { for (int i = 0; i < length - 1; i++) { //趟數 for (int j = i + 1; j < length; j++) { //比較次數 if (arr[i] > arr[j]) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } }
4.2、冒泡排序
- 【冒泡排序】:相鄰元素兩兩比較,比較完一趟,最值出現在末尾
- 第1趟:依次比較相鄰的兩個數,不斷交換(小數放前,大數放後)逐個推進,最值最後出現在第n個元素位置
- 第2趟:依次比較相鄰的兩個數,不斷交換(小數放前,大數放後)逐個推進,最值最後出現在第n-1個元素位置
- …… ……
- 第n-1趟:依次比較相鄰的兩個數,不斷交換(小數放前,大數放後)逐個推進,最值最後出現在第2個元素位置
void bublleSort(int *arr, int length) { for(int i = 0; i < length - 1; i++) { //趟數 for(int j = 0; j < length - i - 1; j++) { //比較次數 if(arr[j] > arr[j+1]) { int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } }
5、折半查找(二分查找)
折半查找:優化查找時間(不用遍歷全部數據)
折半查找的原理:
- 1> 數組必須是有序的
- 2> 必須已知min和max(知道範圍)
- 3> 動態計算mid的值,取出mid對應的值進行比較
- 4> 如果mid對應的值大於要查找的值,那麼max要變小爲mid-1
- 5> 如果mid對應的值小於要查找的值,那麼min要變大爲mid+1
// 已知一個有序數組, 和一個key, 要求從數組中找到key對應的索引位置
int findKey(int *arr, int length, int key) {
int min = 0, max = length - 1, mid;
while (min <= max) {
mid = (min + max) / 2; //計算中間值
if (key > arr[mid]) {
min = mid + 1;
} else if (key < arr[mid]) {
max = mid - 1;
} else {
return mid;
}
}
return -1;
}
6、集合結構 線性結構 樹形結構 圖形結構
- 1.1、集合結構 說白了就是一個集合,就是一個圓圈中有很多個元素,元素與元素之間沒有任何關係 這個很簡單
- 1.2、線性結構 說白了就是一個條線上站着很多個人。 這條線不一定是直的。也可以是彎的。也可以是值的 相當於一條線被分成了好幾段的樣子 (發揮你的想象力)。 線性結構是一對一的關係
- 1.3、樹形結構 說白了 做開發的肯定或多或少的知道xml 解析 樹形結構跟他非常類似。也可以想象成一個金字塔。樹形結構是一對多的關係
- 1.4、圖形結構 這個就比較複雜了。他呢 無窮。無邊 無向(沒有方向)圖形機構 你可以理解爲多對多 類似於我們人的交集關係
7、數據結構的存儲
數據結構的存儲一般常用的有兩種 順序存儲結構 和 鏈式存儲結構
- 2.1 順序存儲結構
發揮想象力啊。 舉個列子。數組。1-2-3-4-5-6-7-8-9-10。這個就是一個順序存儲結構 ,存儲是按順序的 舉例說明啊。 棧。做開發的都熟悉。棧是先進後出 ,後進先出的形式 對不對 ?!他的你可以這樣理解
hello world 在棧裏面從棧底到棧頂的邏輯依次爲 h-e-l-l-o-w-o-r-l-d 這就是順序存儲 再比如 隊列 ,隊列是先進先出的對吧,從頭到尾 h-e-l-l-o-w-o-r-l-d 就是這樣排對的
- 2.2 鏈式存儲結構
再次發揮想象力 這個稍微複雜一點 這個圖片我一直弄好 ,回頭找美工問問,再貼上 例如 還是一個數組
1-2-3-4-5-6-7-8-9-10 鏈式存儲就不一樣了 1(地址)-2(地址)-7(地址)-4(地址)-5(地址)-9(地址)-8(地址)-3(地址)-6(地址)-10(地址)。每個數字後面跟着一個地址 而且存儲形式不再是順序 ,也就說順序亂了,1(地址) 1後面跟着的這個地址指向的是2,2後面的地址指向的是3,3後面的地址指向是誰你應該清楚了吧。他執行的時候是 1(地址)-2(地址)-3(地址)-4(地址)-5(地址)-6(地址)-7(地址)-8(地址)-9(地址)-10(地址),但是存儲的時候就是完全隨機的。明白了?!
8、單向鏈表\雙向鏈表\循環鏈表
還是舉例子。理解最重要。不要去死記硬背 哪些什麼。定義啊。邏輯啊。理解纔是最重要滴
- 3.1 單向鏈表
A->B->C->D->E->F->G->H. 這就是單向鏈表 H 是頭 A 是尾 像一個只有一個頭的火車一樣 只能一個頭拉着跑
- 3.2 雙向鏈表
數組和鏈表區別:
數組:數組元素在內存上連續存放,可以通過下標查找元素;插入、刪除需要移動大量元素,比較適用於元素很少變化的情況
鏈表:鏈表中的元素在內存中不是順序存儲的,查找慢,插入、刪除只需要對元素指針重新賦值,效率高
- 3.3 循環鏈表
循環鏈表是與單向鏈表一樣,是一種鏈式的存儲結構,所不同的是,循環鏈表的最後一個結點的指針是指向該循環鏈表的第一個結點或者表頭結點,從而構成一個環形的鏈。發揮想象力 A->B->C->D->E->F->G->H->A. 繞成一個圈。就像蛇吃自己的這就是循環 不需要去死記硬背哪些理論知識。
9、二叉樹/平衡二叉樹
- 4.1 什麼是二叉樹
樹形結構下,兩個節點以內 都稱之爲二叉樹 不存在大於2 的節點 分爲左子樹 右子樹 有順序 不能顛倒 ,懵逼了吧,你肯定會想這是什麼玩意,什麼左子樹右子樹 ,都什麼跟什麼鬼? 現在我以普通話再講一遍,你把二叉樹看成一個人 ,人的頭呢就是樹的根 ,左子樹就是左手,右子樹就是右手,左右手可以都沒有(殘疾嘛,聲明一下,絕非歧視殘疾朋友,勿怪,勿怪就是舉個例子,i am very sorry) , 左右手呢可以有一個,就是不能顛倒。這樣講應該明白了吧
二叉樹有五種表現形式
1.空的樹(沒有節點)可以理解爲什麼都沒 像空氣一樣
2.只有根節點。 (理解一個人只有一個頭 其他的什麼都沒,說的有點恐怖)
3.只有左子樹 (一個頭 一個左手 感覺越來越寫不下去了)
4.只有右子樹
5.左右子樹都有
二叉樹可以轉換成森林 樹也可以轉換成二叉樹。這裏就不介紹了 你做項目絕對用不到
數據結構大致介紹這麼多吧。理解爲主, 別死記,死記沒什麼用
想要了解和閱讀更多的iOS面試題,可以添加QQ羣:763164022 !羣內有已經整理好的面試題以及答案文檔,同時,也希望大家一起多多交流技術,行情等等!歡迎你的加入~~