单链表
先给出定义部分和相关调试部分
#include <bits/stdc++.h>
using namespace std;
struct ListNode
{
int v;
struct ListNode *next;
}*head;
ListNode* insert(int v)
{
ListNode* p=head;
if(head == NULL)
{
head = new ListNode;
head -> next = 0;
head->v = v;
return head;
}
while(p->next!=NULL)
p = p->next;
p -> next = new ListNode;
p = p ->next;
p->next = NULL;
p -> v =v;
return p;
}
void show()
{
for(ListNode*p = head;p!=NULL;p=p->next)
printf("%d ",p->v);
puts("");
}
单链表翻转
通过三个指针实现.
ListNode*rev(ListNode *head)
{
ListNode *p,*q,*t;
///保证最少有两个节点
if(head == NULL||head -> next == NULL)
return head;
p = NULL;
q = head;
t = head;
while(t!=NULL)
{
t = t -> next;
q->next = p;
p = q;
q = t;
}
return p;
}
调试与验证
void showRev()
{
head = NULL;
show();
head = rev(head);
show();
insert(1);
show();
head = rev(head);
show();
head = rev(head);
insert(2);
show();
head = rev(head);
show();
head = rev(head);
insert(3);
show();
head = rev(head);
show();
head = rev(head);
insert(4);
show();
head = rev(head);
show();
head = rev(head);
}
判环
定义两个指针,一个一次走两个,另一个一次走一个. 如果有环就会相遇
bool hasLoop(ListNode *head)
{
ListNode *p1 , *p2;
p1 = p2 = head;
while(NULL != p1 && NULL != p1 ->next)
{
p1 = p1 -> next;
p1 = p1 -> next;
p2 = p2 -> next;
if(p1 == p2)
return 1;
}
return 0;
}
调试与验证
void showHasLoop1()
{
ListNode *a , *b;
head = NULL;
show();
printf("ans:%d\n",hasLoop(head));
show();
a = insert(1);
show();
printf("ans:%d\n",hasLoop(head));
show();
a -> next = head;
printf("ans:%d\n",hasLoop(head));
}
void showHasLoop2()
{
head = NULL;
insert(1);
insert(2);
insert(3) -> next = head;
printf("ans:%d\n",hasLoop(head));
}
void showHasLoop3()
{
ListNode *a;
head = NULL;
insert(1);
insert(2);
a = insert(3);
insert(4);
insert(5);
insert(6) -> next = a;
printf("ans:%d\n",hasLoop(head));
}
环长
先判环,如果有环,那么就一个指针移动,另一个不动,作为标记.
int circleLen(ListNode *head)
{
ListNode *p1 , *p2;
p1 = p2 = head;
int cnt=0;
while(NULL != p1 && NULL != p1 ->next)
{
p1 = p1 -> next;
p1 = p1 -> next;
p2 = p2 -> next;
if(p1 == p2)
{
p1 = p1 -> next;
for(cnt = 1;p1 != p2;cnt ++)
{
p1 = p1 -> next;
}
break;
}
}
return cnt;
}
验证
void showCircleLen1()
{
ListNode *a , *b;
head = NULL;
show();
printf("ans:%d\n",circleLen(head));
show();
a = insert(1);
show();
printf("ans:%d\n",circleLen(head));
show();
a -> next = head;
printf("ans:%d\n",circleLen(head));
}
void showCircleLen2()
{
head = NULL;
insert(1);
insert(2);
insert(3) -> next = head;
printf("ans:%d\n",circleLen(head));
}
void showCircleLen3()
{
ListNode *a;
head = NULL;
insert(1);
insert(2);
a = insert(3);
insert(4);
insert(5);
insert(6) -> next = a;
printf("ans:%d\n",circleLen(head));
}
环前链长
还是定义两个指针,p1指针先走环长个节点,然后p1和p2步进,再次相遇的时候p2走的步数就是链长.需要注意的是没有环的情况.
int linkLen(ListNode *head)
{
int ret;
int len = circleLen(head);
ListNode *p1, *p2 ;
p1 = p2 = head;
for(int i = len; i ; i-- )
{
p1 = p1 -> next;
}
for(ret = 0;p1 != p2 || (NULL != p1 && len == 0); ret++ )
{
p1 = p1 -> next;
p2 = p2 -> next;
}
return ret;
}
验证
void showLinkLen1()
{
ListNode *a , *b;
head = NULL;
show();
printf("ans:%d\n",linkLen(head));
show();
a = insert(1);
show();
printf("ans:%d\n",linkLen(head));
show();
a -> next = head;
printf("ans:%d\n",linkLen(head));
}
void showLinkLen2()
{
head = NULL;
insert(1);
insert(2);
insert(3) -> next = head;
printf("ans:%d\n",linkLen(head));
}
void showLinkLen3()
{
ListNode *a;
head = NULL;
insert(1);
insert(2);
a = insert(3);
insert(4);
insert(5);
insert(6) -> next = a;
printf("ans:%d\n",linkLen(head));
}
全部代码
#include <bits/stdc++.h>
using namespace std;
struct ListNode
{
int v;
struct ListNode *next;
}*head;
ListNode* insert(int v)
{
ListNode* p=head;
if(head == NULL)
{
head = new ListNode;
head -> next = 0;
head->v = v;
return head;
}
while(p->next!=NULL)
p = p->next;
p -> next = new ListNode;
p = p ->next;
p->next = NULL;
p -> v =v;
return p;
}
void show()
{
for(ListNode*p = head;p!=NULL;p=p->next)
printf("%d ",p->v);
puts("");
}
ListNode*rev(ListNode *head)
{
ListNode *p,*q,*t;
///保证最少有两个节点
if(head == NULL||head -> next == NULL)
return head;
p = NULL;
q = head;
t = head;
while(t!=NULL)
{
t = t -> next;
q->next = p;
p = q;
q = t;
}
return p;
}
void showRev()
{
head = NULL;
show();
insert(1);
show();
head = rev(head);
show();
head = rev(head);
insert(2);
show();
head = rev(head);
show();
head = rev(head);
insert(3);
show();
head = rev(head);
show();
head = rev(head);
insert(4);
show();
head = rev(head);
show();
head = rev(head);
}
bool hasLoop(ListNode *head)
{
ListNode *p1 , *p2;
p1 = p2 = head;
while(NULL != p1 && NULL != p1 ->next)
{
p1 = p1 -> next;
p1 = p1 -> next;
p2 = p2 -> next;
if(p1 == p2)
return 1;
}
return 0;
}
void showHasLoop1()
{
ListNode *a , *b;
head = NULL;
show();
printf("ans:%d\n",hasLoop(head));
show();
a = insert(1);
show();
printf("ans:%d\n",hasLoop(head));
show();
a -> next = head;
printf("ans:%d\n",hasLoop(head));
}
void showHasLoop2()
{
head = NULL;
insert(1);
insert(2);
insert(3) -> next = head;
printf("ans:%d\n",hasLoop(head));
}
void showHasLoop3()
{
ListNode *a;
head = NULL;
insert(1);
insert(2);
a = insert(3);
insert(4);
insert(5);
insert(6) -> next = a;
printf("ans:%d\n",hasLoop(head));
}
int circleLen(ListNode *head)
{
ListNode *p1 , *p2;
p1 = p2 = head;
int cnt=0;
while(NULL != p1 && NULL != p1 ->next)
{
p1 = p1 -> next;
p1 = p1 -> next;
p2 = p2 -> next;
if(p1 == p2)
{
p1 = p1 -> next;
for(cnt = 1;p1 != p2;cnt ++)
{
p1 = p1 -> next;
}
break;
}
}
return cnt;
}
void showCircleLen1()
{
ListNode *a , *b;
head = NULL;
show();
printf("ans:%d\n",circleLen(head));
show();
a = insert(1);
show();
printf("ans:%d\n",circleLen(head));
show();
a -> next = head;
printf("ans:%d\n",circleLen(head));
}
void showCircleLen2()
{
head = NULL;
insert(1);
insert(2);
insert(3) -> next = head;
printf("ans:%d\n",circleLen(head));
}
void showCircleLen3()
{
ListNode *a;
head = NULL;
insert(1);
insert(2);
a = insert(3);
insert(4);
insert(5);
insert(6) -> next = a;
printf("ans:%d\n",circleLen(head));
}
int linkLen(ListNode *head)
{
int ret;
int len = circleLen(head);
ListNode *p1, *p2 ;
p1 = p2 = head;
for(int i = len; i ; i-- )
{
p1 = p1 -> next;
}
for(ret = 0;p1 != p2 || (NULL != p1 && len == 0); ret++ )
{
p1 = p1 -> next;
p2 = p2 -> next;
}
return ret;
}
void showLinkLen1()
{
ListNode *a , *b;
head = NULL;
show();
printf("ans:%d\n",linkLen(head));
show();
a = insert(1);
show();
printf("ans:%d\n",linkLen(head));
show();
a -> next = head;
printf("ans:%d\n",linkLen(head));
}
void showLinkLen2()
{
head = NULL;
insert(1);
insert(2);
insert(3) -> next = head;
printf("ans:%d\n",linkLen(head));
}
void showLinkLen3()
{
ListNode *a;
head = NULL;
insert(1);
insert(2);
a = insert(3);
insert(4);
insert(5);
insert(6) -> next = a;
printf("ans:%d\n",linkLen(head));
}
int main()
{
showLinkLen3();
}
堆
定义和性质:
- 二叉堆是完全二叉树
- 父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值
- 每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)
(以下例子使用大根堆)
建立(维护)
- 按倒序扫一遍父节点
- 对于每个父节点找到最大的一个子节点,若该节点严格大于父节点,则交换父子的值,再对该节点递归的进行第二步,直到没有子节点大于父节点,此时继续执行第一步.
思考:当我们执行第 2 步的时候,我们就是在维护这个子堆的性质.假如 子堆A 满足性质,那么这个 子堆A 的 父节点B 一定能在少于 logn 次交换后,使子堆 A∪B 满足堆的性质.
插入
把要插入的数当成堆的最后一个元素,要维护堆把该节点与父节点进行交换,递归执行,直到满足堆的性质(该节点严格小于父节点)
删除
大根堆规定只能删除最大元素,也就是头结点.步骤如下:
- 移除头结点
- 将最后一个节点换到头部(代码中是 1,2 步结合,将头结点与最后一个节点置换,然后长度 -1 )
- 执行建立时第 2 步操作,维护堆的性质
排序
利用大根堆的性质,每次可以删除最大的元素,我们把这个元素放在队列最后不去考虑他,递归执行找第 n-i 大的元素放在队列尾部.这样就形成了一个非递减数列.
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5;
///BigRoot
struct heap
{
int A[MAXN] , n;
void init(int _n , int m)
{
n = _n;
srand(time(NULL));
for(int i=0;i<n;i++)
A[i] = rand() % m;
}
void show()
{
for(int i=0;i<n;i++)
printf("%d ",A[i]);
puts("");
}
int getLs(int num)
{
return ( ( num + 1 ) << 1 ) - 1;
}
int getRs(int num)
{
return ( num + 1 ) << 1 ;
}
int getF(int num)
{
return ( num - 1 ) >> 1;
}
void _fixDown(int num)
{
while(num<n)
{
int ls = getLs(num) , rs = getRs(num);
printf("\t%d %d\n",ls,rs);
int m ;
if (ls >= n)
break;
else if ( rs >= n)
m = ls;
else
m = ( A[ls] < A[rs] ? rs : ls );
if( A[num] < A[m] )
{
printf("\tswap(%d,%d)\n",num,m);
swap(A[num],A[m]);
num = m;
}
else
break;
}
}
void build()
{
for(int i = getF(n) ; i >= 0 ; i-- )
printf("B:%d\n",i),
_fixDown(i);
}
void insert(int v)
{
int num = n;
A[n++] = v;
int f;
while(num && A[num] > A[ f = getF(num) ] )
{
printf("\tswap(%d,%d)\n",num,f);
swap(A[num] , A[f]);
num = f;
}
}
void remove()
{
n--;
printf("\tswap(%d,%d)\n",n,0);
swap( A[n] , A[0] );
_fixDown(0);
}
void sort()
{
int _n = n;
build();
while(n)
remove();
n = _n;
}
}h;
char hit[10000];
int offset = 0;
void pt(char *s)
{
sprintf(hit+offset,s);
offset += strlen(s);
}
int AT[] = {2,1,6,1,2,2,6,2,8,5};
int main()
{
pt("i v\tinsert(v)\n");
pt("r\tremove()\n");
pt("p\tprint()\n");
pt("s\tsort()\n");
pt("h\thelp()\n");
h.init(10,10);
memcpy(h.A,AT,sizeof(AT));
h.show();
h.build();
h.show();
char op[5];
while(scanf("%s",op)!= EOF)
{
int v;
switch (op[0])
{
case 'i':
scanf("%d",&v);
h.insert(v);
break;
case 'r':
h.remove();
break;
case 'p':
h.show();
break;
case 's':
h.sort();
break;
case 'h':
puts(hit);
break;
case 'q':
return 0;
}
}
return 0;
}