链表操作
- 头插法
1 | void listHeadInsert(pStudent_t *ppHead,Student_t **ppTail,int val) |
先申请新结点空间,给新结点赋值,判断链表是否为空,空则头尾都指向新结点,不为空则pNew->next=*ppHead, *ppHead=pNew,及时更新头指针
- 尾插法
1 | void listTailInsert(pStudent_t *ppHead,Student_t **ppTail,int val) |
(*ppTail)->next=pNew, *ppTail=pNew
- 有序插入
1 | void listSortInsert(pStudent_t *ppHead,Student_t **ppTail,int val) |
先判断链表是否为空,再判断新插入节点的值是否小于头结点的值,否则向后遍历遍历到pCur的值大于新值,插到pCur前面,若直到pCur为空都不大于新值,插入链表尾部。
- 链表删除
1 | void listDelete(pStudent_t *ppHead,Student_t **ppTail,int deleteNum) |
先判断链表是否为空,然后判断头结点是否是要删除的节点,再遍历链表,找要删除的节点
- 链表修改
1 | void listModify(pStudent_t pHead,int num,float score) |
遍历链表,找到要修改的节点
层次建立二叉树
1 | typedef char ElemType; |
利用辅助队列实现
排序算法
常用算法复杂度表
- 选择排序
1 | void arrSelect(int *arr) |
每次选择最大的数放在其最终位置
- 插入排序
1 | void arrInsert(int *arr) |
每次都拿第i个数从后往前比,若这个数比第i个数大就将其往后移直到找到第i个数的位置
- 希尔排序
1 | void arrShell(int *arr) |
插入排序的变形,将所有1改成gap,gap第一次是N/2,接下来每次都/2
- 快排
1 | int partition(int *arr,int left,int right) |
每次利用partition函数找到一个数,使他的左边都小于它,右边都大于它,递归
- 堆排
1 | void adjustMaxHeap(int *arr,int adjustPos,int arrLen) |
堆排序对数组排序,心中有棵树,建堆的过程最为重要
- 计数排序
1 | void arrCount(int *arr) |
空间换时间,值的范围太大的时候效率会变低
qsort可以用来对链表排序,将链表每个节点赋给指针数组,再对该数组进行排序
封装成类似于qsort接口的堆排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70//堆排序
void swapp(char *p1, char *p2, size_t size)
{
char p;
int i;
for(i=0;i<size;i++)
{
p = *p1;
*p1 = *p2;
*p2 = p;
p1++;
p2++;
}
}
void adjustMaxHeap(void *base, void *cur, size_t num, size_t size)
{
char *dad = (char*)cur;
char *lo = (char*)base;
char *hi = (char*)base + size*(num);
char *son = (char*)base + (dad-lo)*2 + size;
while (son <= hi)
{
if((son+size)<=hi&&*son<*(son+size))
{
son+=size;
}
if(*dad<*son)
{
swapp(dad, son,size);
dad = son;
son =lo + (dad-lo)*2 + size;
}
else
{
break;
}
}
}
void arrHeap(void *base, size_t num, size_t size, int (*compare)(const void *, const void *))
{
char *lo, *hi, *cur, *t;
lo = (char*)base;
hi = (char*)base + size*(num-1);
for(cur=lo+num/2*size-size;cur>=lo;cur-=size)
{
adjustMaxHeap(base,cur,num,size);
}
swapp(lo, hi, size);
for(cur=hi-size;cur>lo;cur-=size)
{
adjustMaxHeap(base,lo,(cur-lo)/size,size);
swapp(lo, cur, size);
}
if(compare<0)
{
cur=lo;
t=hi;
while(cur<t)
{
swapp(cur, t,size);
cur+=size;
t-=size;
}
}
}这样堆排序可以排序任意数据类型的数组,结构体数组等。
红黑树
1. 红黑树特点
- 节点有红色和黑色,根是黑色节点
- 每个红色节点都必须有两个黑色子节点
- 从根节点到每个叶子都有相同数量的黑色节点
2. 插入时的情况(新结点初始时是红色)
新结点的父亲节点是黑色,直接插入
新结点的父节点和叔叔节点都是红色,但祖父节点是黑色。把祖父节点染成红色,父亲和叔叔节点染成黑色,再插入。
新结点的父节点是红色,叔叔节点是黑色或者缺失,插入节点,父亲节点,祖父节点呈之字形,进行左旋(或右旋):
情形3此时还不满足红黑树所有性质,此时状态可以称为情形4,要对顶端的节点进行左旋(右旋)并将顶端节点染成红色,父亲的红色节点染成黑色,就可以构成红黑树