W1 概念易错点
知识点
1、 算法vs程序
. | 算法 | 程序 |
---|---|---|
有穷性 | 必须是有穷的 | 可以是无穷的 |
正确性 | 必须是正确的 | 可以是错误的 |
描述方法 | 伪代码、程序描述语言等 | 只能用程序描述语言编写并可以运行 |
2、有序表——仅描述了逻辑关系
3、循环队列——是一种数据结构,是用顺序表表示的队列,没有使用队列的链式存储结构表示的循环队列
4、栈——是一种抽象数据类型,可采用顺序存储或链式存储,只表示逻辑结构
5、链式存储设计时,结点内 的存储单元地址一定连续。
6、算法原地工作的含义是指所需的辅助空间为常量,而不是不需要任何额外的辅助空间。
7、加法规则
T ( n ) = T 1 ( n ) + T 2 ( n ) = O ( f ( n ) ) + O ( g ( n ) ) = O ( m a x ( f ( n ) , g ( n ) ) ) T(n) = T_1(n)+T_2(n)=O(f(n))+O(g(n)) = O(max(f(n), g(n))) T(n)=T1(n)+T2(n)=O(f(n))+O(g(n))=O(max(f(n),g(n)))
8、乘法规则
T ( n ) = T 1 ( n ) × T 2 ( n ) = O ( f ( n ) ) × O ( g ( n ) ) = O ( f ( n ) × g ( n ) ) T(n) = T_1(n) \times T_2(n) = O(f(n)) \times O(g(n)) = O(f(n) \times g(n)) T(n)=T1(n)×T2(n)=O(f(n))×O(g(n))=O(f(n)×g(n))
9、常见渐进时间复杂度
O ( 1 ) < O ( l o g 2 n ) < O ( n ) < O ( n l o g 2 n ) < O ( n 2 ) < O ( n 3 ) < O ( 2 n ) < O ( n ! ) < O ( n n ) O(1) < O(log_2n)<O(n)<O(nlog_2n)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n) O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)
小题目
1、已知两个长度分别为m和n的升序链表,若将它们合并为一个长度为m+n的降序链表,则最坏情况下的时间复杂度是(O(max(m, n)) )。
首先,看到升序变降序,选择头插法较好。
具体操作:每次取出m和n中剩下的最小元素,插入到head结点后,类似于归并排序的思想。若某一个表比较完毕,另一个表的余下元素直接依次用头插法插入到头结点后。
参考代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode{
int data;
struct LNode *next;
}LNode;
//尾插法创建前两个升序链表
LNode* List_TailInsert(LNode *L, int len)
{
LNode *s, *r;
r = L = (LNode*)malloc(sizeof(LNode));
for(int i = 0; i < len; i++){
s = (LNode*)malloc(sizeof(LNode));
scanf("%d", &(s->data));
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
int main(void){
int m, n;
printf("请输入第一个升序链表m的长度:");
scanf("%d", &m);
printf("请输入的一个表的%d个值(升序),用空格隔开:\n", m);
//第一个升序链表m
LNode *mL = List_TailInsert(mL, m);
printf("请输入第二个升序链表n的长度:");
scanf("%d", &n);
printf("请输入的二个表的%d个值(升序),用空格隔开:\n", n);
//第二个升序链表n
LNode *nL = List_TailInsert(nL, n);
//合并为一个降序链表
LNode *p