初始数据集的排列顺序对算法的性能无影响的算法有:选(直接选择排序)归(归并排序)堆(堆排序)
影响排序算法时间复杂度的主要原因是比较的次数
基于比较的排序算法有:
- 直接插入排序
- 冒泡排序
- 简单选择排序
- 希尔排序
- 快速排序
- 堆排序
- 归并排序
基数排序、桶排序都属于分配式排序,且都是稳定排序算法
比较次数与序列初始状态无关的排序方法
- 简单选择排序
- 二分插入排序
[X-Y]补 = [X]补-[Y]补 = [X]补+[-Y]补
二进制的原码、反码、补码,对于有符号数而言:
- 二进制的最高位是符号位:0表示正数(+),1表示负数(-)
- 正数的原码、反码、补码都一样
- 负数的反码 = 它的符号位不变,其他位取反
- 负数的补码 = 它的反码 +1
- 0的反码、补码都是0
写了一下链表的增删改查
struct ListNode
{
int val;
ListNode* next;
ListNode(int x) :val(x),next (NULL) {};
};
ListNode* creat(vector<int> vec) {//利用传入的vector建立一个新的链表。
ListNode* p, * pre, * head;
head = new ListNode(vec[0]);
pre = head;
for (int i = 1; i < 5; i++) {
p = new ListNode(vec[i]);
pre->next = p;
pre = p;
}
return head;
}
bool search(ListNode* head, int target)
{
ListNode* dummy = head;
while (dummy != NULL) {
if (dummy->val == target)return true;
dummy = dummy->next;
}
return false;
}
bool deleteNode(ListNode* head, int target) {//删除第一个val等于target的结点
ListNode* dummy = new ListNode(-1);//使用一个虚拟头节点避免判断边界情况
dummy->next = head;
while (dummy != NULL) {
if (dummy->next->val == target)
{
dummy->next = dummy->next->next;
return true;
}
dummy = dummy->next;
}
return false;
}
bool insertNode(ListNode* head, int target) {//插入到第一个val大于target的结点之前
ListNode* dummy = new ListNode(-1);
dummy->next = head;
while (dummy != NULL) {
if (dummy->next->val >= target) {
ListNode* temp = new ListNode(target);
temp->next = dummy->next;
dummy->next = temp;
return true;
}
dummy = dummy->next;
}
return false;
}
灵活使用虚拟头节点,避免了繁琐的边界判别情况。这里我仅返回了是否成功,在实际情况下,可按需要返回dummy或者dummy->next。