随笔分类 - 数据结构与算法
摘要:选择排序是一种简单直观的排序算法,其核心思想是:遍历数组,从未排序的序列中找到最小元素,将其放到已排序序列的末尾。时间复杂度:O(n^2)稳定性 :不稳定 1: /* 2: * @brief selection sort 3: */ 4: void 5: selection_sort(int a[], int n) 6: { 7: int i, j, min, tmp; 8: 9: for (i = 0; i < n - 1; ++i) { 10: min = i; 11: for (j...
阅读全文
摘要:直接插入排序是一种比较容易理解的排序算法,其核心思想是遍历数组,将数组中的元素逐个插入到已排序序列中。时间复杂度:O(n^2)稳定性:稳定实现: 1: /* @brief insetion sort 2: * insert the new element to the sorted subarray 3: */ 4: void 5: insertion_sort(int a[], int n) 6: { 7: int i, j, num; 8: 9: for (i = 1; i < n; ++i) { 10: num ...
阅读全文
摘要:冒泡排序是最基本的排序算法之一,其核心思想是从后向前遍历数组,比较a[i]和a[i-1],如果a[i]比a[i-1]小,则将两者交换。这样一次遍历之后,最小的元素位于数组最前,再对除最小元素外的子数组进行遍历。进行n次(n数组元素个数)遍历后即排好序。外层循环为n次,内层循环分别为n-1, n-2…1次。时间复杂度: O(n^2)稳定性:稳定实现: 1: /* @brief bubble sort 2: * move the smallest element to the front in every single loop 3: */ 4: void 5: bub...
阅读全文
摘要:如何判断一个数是2的幂,主要是要找出2的幂次方的数的特点。我们知道,1个数乘以2就是将该数左移1位,而2的0次幂为1, 所以2的n次幂(就是2的0次幂n次乘以2)就是将1左移n位, 这样我们知道如果一个数n是2的幂,则其只有首位为1,其后若干个0,必然有n & (n - 1)为0。(在求1个数的二进制表示中1的个数的时候说过,n&(n-1)去掉n的最后一个1)。因此,判断一个数n是否为2的幂,只需要判断n&(n-1)是否为0即可。实现: 1: bool powerof2(unsigned int n) 2: { 3: return ((n & (n -1)) =
阅读全文
摘要:实现1:使用按位与和移位操作符,逐位进行统计。需要注意的是,对于有符号的右移操作符号位如何处理是不确定的,因此我们在进行移位操作前要将有符号型转换为无符号型。 1: int bitcount(int n) 2: { 3: unsigned int count = 0, m = n; /* 注意, 我们这里需要将输入转化为无符号类型 */ 4: 5: while (m != 0) { 6: if ((m & 0x01) == 1) { 7: ++count; 8: ...
阅读全文
摘要:1.单链表逆序实现1:遍历: 1: /* 2: * 遍历链表, 将每个结点的next置为其前驱 3: * 遍历过程中需要额外的指针来记录结点的前驱和后继 4: */ 5: LinkList ReverseList(LinkList L) 6: { 7: if (!L || !L->next) { 8: return L; 9: } 10: 11: Node *pre, *cur, *next; 12: 13: pre = next = NULL; 14: cur = L->next...
阅读全文
摘要:线性表的顺序存储结构要求逻辑关系上相邻的元素在物理位置上也相邻,这样方便了随机存取,但是在插入和删除元素时,需要移动大量元素,而线性表的链式存储则不要求逻辑上相邻的元素在物理位置上也相邻,因此它没有顺序存储结构的可随机存取的优点,不过在插入和删除元素时比较方便。单链表单链表可由头指针唯一确定,在C语言中可用“结构指针”来描述: 1: typedef struct Node { 2: ElemType data; 3: struct Node *next; 4: }Node, *LinkList;有时,我们会在单链表的第一个结点之前附设一个结点,称之为头结...
阅读全文
摘要:线性表的顺序存储是指用一组地址连续的存储单元一次存储线性表的数据元素。在C语言中,可以使用动态数组来实现线性表的顺序存储。定义: 1: #define LIST_INIT_SIZE 100 2: #define LIST_INCREMENT 10 3: 4: typedef struct { 5: ElemType *elem; 6: int length; 7: int listsize; 8: }SqList;操作: 1: InitList(L); /* 构造线性表...
阅读全文
摘要:给定一整形数组a,要求从中找出最大的数和最小的数,并计算时间复杂度。实现1:遍历数组,每次取数组中一个元素, 分别与当前最大值和最小值进行比较,时间复杂度O(2n) 1: void search(int a[], size_t n, int &max, int &min) 2: { 3: int i; 4: max = min = a[0]; 5: 6: for (i = 1; i < n; ++i) { 7: if (a[i] > max) 8: max = a[i]; 9: ...
阅读全文
摘要:在数学中, 辗转相除法,又称欧几里得算法,是求最大公约数的算法。其算法步骤:a,b相除将b赋值给a将余数赋值给b若b为0, 则a为最大公约数;否则执行步骤1-3直至b为0。例如计算6和4的最大公约数:a=6,b=4,a/b余数为2将b赋值给a,a=4将余数赋值给b,b=2b不为0, 重复执行1-3a=4,b=2,a/b余数为0将b赋值给a,a=2将余数赋值给b,b=0b为0, 则此时的a为最大公约数伪代码实现: 1: function gcd(a, b) 2: while b != 0 3: t := b 4: b := a mod b ...
阅读全文
摘要:字符串的各种操作向来也是面试官的最爱,从简单的开始:逆序输出字符串。实现1: 1: void reverse(const char *str) 2: { 3: ssize_t i; 4: size_t len = strlen(str); 5: 6: for (i = len; i >=0; --i) { 7: printf("%c", *(str + i)); 8: } 9: printf("\n"); 10: }这里要注意的是循环变量i一定要声明成带符号类型的, 否则就会陷入死循环了。...
阅读全文
摘要:在排序算法中,我们经常需要交换两个数的值, 在进入算法之前,先在这里复习一下两数交换的实现方法,算是开胃小菜。实现1:最简单的也是最常用的实现: 1: void swap(int *a, int *b) 2: { 3: int temp = *a; 4: *a = *b; 5: *b = temp; 6: }然而面试官们常常并不满意这样的实现,他们很有可能要求我们不能使用其它内存,那么又有了下面两个实现方法。实现2:异或: 1: void swap(int *a, int *b) 2: { 3: *a = *a ^ ...
阅读全文

浙公网安备 33010602011771号