typedef struct node{
int data;
struct node *next;
}*list;
注意必须加引用,不加引用会断链
void deletenode(list &head, int x){ //必须加引用
struct node *p;
if(head == NULL) return;
else if(head->data == x){
p = head;
head = head->next; //这里不会断链 head->next = head->next->next
free(p);
deletenode(head, x);
}
else{
deletenode(head->next, x);
}
}
思路:
代码:
void InsertSort_Node(list &head){
struct node *p = head->next,*nextp, *q;
head->next = NULL;
while(p!=NULL){
nextp = p->next;
q = head;
while(q->next!=NULL && q->next->data < p->data){//找到插入位置
q = q->next;
}
p->next = q->next; //插入
q->next = p;
p = nextp;
}
}
思路:
代码:
void BubbleSort_Node(list &head){
struct node *pre,*p,*q;
struct node *tail = NULL; //尾指针,每次冒泡排序之后,最后一个元素都已经确定顺序
while(head->next!= tail){ //冒泡次数
pre = head;
p = head->next;
q = p->next;
while(p->next!=tail){ //冒泡长度
if(p->data > q->data){ //如果前一个数比后一个数大,交换指针
pre->next = q;
p->next = q->next;
q->next = p;
}
else{
p = p->next; //不用交换指针,继续往下找
}
pre = pre->next; //p指针已经在上面的if和else中移动了,无需再移动
q = p->next;
}
tail = p; //经过一次冒泡,当前最后一个元素已经排好序,tail前移
}
}
思路:
代码:
list Merge_Node(list head1, list head2){ //合并两个有序链表
list newhead = (list)malloc(sizeof(struct node));
list p = newhead; //工作指针
while(head1 != NULL && head2 !=NULL){
if(head1->data > head2->data){
p->next = head2;
head2 = head2->next;
}
else{
p->next = head1;
head1 = head1->next;
}
p = p->next;
}
if(head1!=NULL) p->next = head1;
if(head2!=NULL) p->next = head2;
return newhead->next;
}
list TwoRoadMergeSort_Node(list head){
if(head == NULL || head->next == NULL) return head;
list fast = head;
list slow = head;
while(fast->next != NULL && fast->next->next != NULL){
fast = fast->next->next;
slow = slow->next;
}
list mid = slow->next; //找到中点
slow->next = NULL;
list left = TwoRoadMergeSort_Node(head); //递归找中点
list right = TwoRoadMergeSort_Node(mid);
return Merge_Node(left, right); //归并
}
思路:
代码:
int Length_Node(list head){//不带头结点 求链表长度
int num = 0;
list p = head;
while(p!=NULL){
num++;
p = p->next;
}
return num;
}
list FindSameNode(list head1, list head2){
int len1 = Length_Node(head1);
int len2 = Length_Node(head2);
list longlist, shortlist;
int dist;
if(len1>len2){ //找到长的链表与短的链表
dist = len1 - len2;
longlist = head1;
shortlist = head2;
}
else{
dist = len2 - len1;
longlist = head2;
shortlist = head1;
}
while(dist){ //长的链表先走完更长的那部分
longlist = longlist->next;
dist--;
}
while(longlist != NULL){ //找公共节点
if(longlist == shortlist){
return longlist;
}
else{
longlist = longlist->next;
shortlist = shortlist->next;
}
}
return NULL; //未找到
}
思路:
代码:
list DivlistToTwo(list &head1){
list p = head1->next,q,p1,p2; //p1,p2为head1,head2工作指针
list head2 = (list)malloc(sizeof(struct node));
head1->next = NULL;
p1 = head1; //工作指针指向对应头结点
p2 = head2;
int num = 1; //添加计数器
while(p!=NULL){ //遍历p节点
if(num%2==1){ //奇数节点
p1->next = p;
p1 = p1->next;
}
else{ //偶数节点
p2->next = p;
p2 = p2->next;
}
num++; //继续遍历
p = p->next;
}
if(p1) p1->next =NULL; //尾部置空
if(p2) p2->next =NULL;
return head2; //返回另外一个节点
}
思路:
代码:
list FindPublicNode(list A, list B){
list pa = A->next, pb = B->next,pc,temp; //pa,pb,pc为A,B,C的工作指针,temp申请新的节点并入C中
list C = (list)malloc(sizeof(struct node));
pc = C;
while(pa != NULL && pb != NULL){
if(pa->data < pb->data){ //pa小,pa往前走
pa = pa->next;
}
else if(pb->data < pa->data){ //pb小,pb往前走
pb = pb->next;
}
else{ //两个节点相同
temp = (struct node *)malloc(sizeof(struct node));
temp->data = pa->data; //加入C中
pc->next = temp;
pc = pc->next; //工作指针继续往后找
pa = pa->next;
pb = pb->next;
}
}
pc->next = NULL;
return C;
}
思路:
代码:
void InterNode(list &A, list B){
list pa = A, pb = B->next,temp; //两个工作指针
while(pa->next!=NULL && pb !=NULL){
if(pa->next->data < pb->data){ //pa更小,删除节点pa->next
temp = pa->next;
pa->next = pa->next->next;
free(temp);
}
else if(pb->data < pa->next->data){//pb更小,继续往后找,看看有无更大的
pb = pb->next;
}
else{ //相同了,就继续往后找
pb = pb->next;
pa = pa->next;
}
}
while(pa->next!=NULL){ //后面还有节点,继续删除
temp = pa->next;
pa->next = pa->next->next;
free(temp);
}
}
思路:
代码:
bool IsPartNode(list A, list B){
list pa = A->next, pb = B->next,p = A->next; //pa,pb为比较节点, p为遍历节点
while(pa != NULL && pb != NULL){ //遍历节点
if(pa->data == pb->data){ //相同就继续比较
pa = pa->next;
pb = pb->next;
}
else{ //不同的话,pb从头开始比较,pa从下一个节点开始比较
p = p->next;
pb = B->next;
pa = p;
}
}
if(pb == NULL) return true; //pb遍历完,说明找到了
else return false; //pb没遍历完,说明没找到
}
思路:
代码:
void ReVerSeTwoNode(list &head){
int flag = 1;
if(head == NULL ||head->next == NULL) return; //只有一个节点,或者没有节点,直接返回
list p = head->next, pre = head,prepre=head; //交换两个节点,需要保存三个节点
while(p!=NULL){
if(flag){ //不带头结点的时候,第一次交换和后序交换有所区别
pre->next = p->next;
p->next = pre;
head = p;
flag = 0;
}
else{ //重新构建三个节点的指向
pre->next = p->next;
p->next = pre;
prepre->next = p;
}
if(pre->next ==NULL ||pre->next->next == NULL) break; //已经反转完或者只剩下一个节点,不用交换了
prepre = pre; //重新分配三个节点
pre = pre->next;
p = pre->next;
}
}
思路:
代码:
list MergeTwoList(list head1, list head2){//默认不带头结点
list newhead = (struct node *)malloc(sizeof(struct node));
list p1 = head1, p2 = head2,p = newhead;
while(p1 != NULL && p2 != NULL){//合并两个链表
if(p1->data > p2->data){ //p1大于p2
p->next = p2;
p = p->next;
p2 = p2->next;
}
else if(p1->data < p2->data){//p2大于p1
p->next = p1;
p = p->next;
p1 = p1->next;
}
else{ //p1等于p2
p->next = p1;
p = p->next;
p1 = p1->next;
p2 = p2->next;
}
}
if(p1!=NULL){ //处理剩余节点
p->next = p1;
}
else{
p->next = p2;
}
return newhead->next; //返回不带头结点的单链表
}
思路:
代码:
bool FindResKNode(list head, int k){
int i =0;
list p1 = head, p2 = head;
while(p1!=NULL){
if(i<k){ //没到p1继续走,计数器加1
i++;
}
else{ //到了,两个指针一起走
p2 = p2->next;
}
p1 = p1->next;
}
if(i == k){ //找到了,输出节点 返回1
printf("%d ",p2->data);
return 1;
}
else{ //没找到,返回0
return 0;
}
}
思路:
代码:
void FindMinNode(list &head){
list pre=head,p=head,minp = head,minpre = head;
while(p!=NULL){
if(p->data < minp->data){ //找到最小节点
minpre = pre;
minp = p;
}
pre = p; //不断遍历
p = p->next;
}
if(minp == head) return; //如果最小节点就是头结点,不用操作
else{
minpre->next = minp->next; //链接到最前面
minp->next = head;
head = minp;
}
visitnode(head);
}
思路:
代码:
list IsLoopAndFindStart(list head){
list slow = head, fast = head; //快慢指针
while(fast!=NULL && fast->next!=NULL){
slow = slow->next;
fast = fast->next->next;
if(slow==fast){ //存在环
list p1 = head;
list p2 = slow;
while(p1!=p2){ //两个指针找到起始节点
p1 = p1->next;
p2 = p2->next;
}
return p1; //返回起始位置节点
}
}
}
思路:
代码:
void DelAbsSameNode(list &head, int n){
int hash[n+1] = {0};
list p = head,pre;
while(p!=NULL){
if(hash[abs(p->data)] < 1){ //如果只出现一次,继续往下找,hash表对应的数+1
hash[abs(p->data)]++;
pre = p;
p = p->next;
}
else{ //否则删除p节点,然后继续p重新指向
pre->next = p->next;
free(p);
p = pre->next;
}
}
}
思路:
代码:
void ResAndInsert(list &L){
list p,nextp,mid,slow = L->next,fast = L->next,nextmid;
while(fast!=NULL && fast->next!=NULL){ //找到中点
slow = slow->next;
fast = fast->next->next;
}
mid = slow->next;
slow->next = NULL; //保存中点,然后断链
p = mid->next; //p为工作节点
mid->next = NULL; //头插法到mid中
while(p!=NULL){
nextp = p->next;
p->next = mid;
mid = p;
p = nextp;
}
p = L->next; //准备插入
while(p!=NULL && mid!=NULL){
nextmid = mid->next; //保存下一个节点
mid->next = p->next; //插入
p->next = mid;
p = p->next->next; //p后移
mid = nextmid; //mid后移
}
}
思路:
代码:
void LinkTwoNode(list &h1, list h2){
list tail1 = h1, tail2 = h2;
while(tail1->next!=h1){ //找到 h1尾结点
tail1 = tail1->next;
}
while(tail2->next!=h2){ //找到h2尾结点
tail2 = tail2->next;
}
tail1->next = h2; //接链
tail2->next = h1;
}
思路:
代码:
void FindMinAndOut(list &head){
list pre = head,p = head->next,minp =head->next,minpre;
while(head->next!=head){ //只有一个节点的时候跳出循环
pre = head;p = head->next;
minpre= head; minp =head->next;
while(p != head){ //循环找到最小元素
if(p->data < minp->data){
minp = p; //有更小,进行更新
minpre = pre;
}
pre = p; //继续往下找
p = p->next;
}
printf("当前最小值为%d\n",minp->data);
minpre->next = minp->next; //删除最小值
free(minp);
}
}
思路:
代码:
typedef struct dnode{
int data;
int freq;
struct dnode *llink, *rlink;
}*dlist;
int LeverUp(dlist &head){
int min;
dlist minp, p = head->right, tail = head;
while(p!=NULL){ //先清除所有左指针
p->left = NULL;
p = p->right;
}
while(true){ //每次找最小
p = head->right;
min = MAX;
while(p->right != NULL){
if(p->left!=NULL) p = p->right; //p左指针不为空,说明已经在序列中,不用排序
else if(p->data < min){ //记录更小值
min = p->data;
minp = p;
p = p->right;
}
else p = p->right; //不是最小值继续找
}
if(min == MAX){
return 1; //遍历一轮没变化,说明已经排好序
}
minp->left = tail; //头插法插入左指针
tail = minp;
}
}
思路:
代码:
typedef struct dnode{
int data;
int freq;
struct dnode *llink, *rlink;
}*dlist;
void Locate(dlist head, int x){
dlist p = head->rlink,q;
while(p != NULL && p->data != x) p = p->rlink; //找到节点值为x的节点
p->freq++; //访问频度加1
if(p!=NULL){ //找到节点
p->freq++; //频度加1
if(p->llink == head) return; //第一个节点,不用调整
q = p; //保存需要操作的节点
p->llink->rlink = p->rlink; //断开p左右节点的链并接上
if(p->rlink!=NULL) //右链得保证存在才能接
p->rlink->llink = p->llink;
p = q->llink; //从q的前一个结点找到q的freq大的节点
while(p != head && p->freq < q->freq) p = p->llink; //找到需要插入的节点
if(p->rlink==NULL){ //q插到p节点前 ,注意这里的插法
q->llink = p;
q->rlink = p->rlink;
p->rlink = q;
}
else{ //不是插到最后一个节点
p->rlink->llink = q;
q->llink = p;
q->rlink = p->rlink;
p->rlink = q;
}
}
}
思路:
代码:
dlist DNodeChange(dlist head){
dlist tail = head->left,p=head->right;
dlist q;
int count = 1; //从第一个节点开始计数
while(p!=tail){
if(count%2==0){
q = p->right; //q保存下一个节点
p->left->right = p->right; //先断链
p->right->left = p->left;
p->right = tail->right; //在尾指针进行头插法
tail->right = p;
p->right->left = p;
p->left = tail;
p = q; //p指向下一个节点
}
else{
p = p->right;
}
count++;
}
return head;
}