双向循环链表.cpp
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include "dclist.h"
/*
作业1:补全双向循环链表代码
作业2:单链表习题
*/
//循环链表可执行的操作:(增删改查)
//初始化
void Init_dclist(PDClist pl)
{
assert(pl != NULL);
if(NULL == pl)
return;
//pl->data; 头结点的数据域不使用 浪费掉
pl->next = pl;
pl->prior = pl;
}
//头插
bool Insert_head(PDClist pl, int val);
//尾插
bool Insert_tail(PDClist pl, int val);
//按位置插入
bool Insert_pos(PDClist pl, int pos, int val);
//头删
bool Del_head(PDClist pl);
//尾删
bool Del_tail(PDClist pl);
//按位置删除
bool Del_pos(PDClist pl, int pos);
//按值删除,删除遇到的第一个值为val的节点 如果值为val的节点不存在,则返回false
bool Del_val(PDClist pl, int val);
//查找 查找值为val的第一个节点,找到则返回其节点地址,否则返回NULL
PDClist Search(PDClist pl, int val);
//判空
bool IsEmpty(PDClist pl);
//获取循环链表有效元素个数
int Get_length(PDClist pl);
//打印
void Show(PDClist pl);
//清空
void Clear(PDClist pl);
//销毁1 一直头删的方式释放内存
void Destroy(PDClist pl);
//销毁2
void Destroy2(PDClist pl);
//寻找值为val的节点的前驱
PDClist Get_prior(PDClist pl, int val);
//寻找值为val的节点的后继
PDClist Get_next(PDClist pl, int val);
单链表 习题
第一题 单链表逆置 掌握 “一直头插”。
void Reverse(PNode plist)
{
//assert 头节点存在
Node*p=plist->next;//让p指向第一个有效节点的位置(但这个位置有可能NULL)
Node*q=NULL;
plist->next=NULL;//或者调用初始化函数让next变为NULL
while(p!=NULL)
{
q=p->next;
Insert_head(plist,p->data)
free(p);
p=q;
}
}
int main()//测试程序
{
Node head;
Init_list(&head);
for(int i;i<0;i++)
{
Insert_pos(&head,i,i+1)
}
show(&head);
Reverse(&head);
}
第二题 单链表删除任意一点o(1)时间复杂度完成
用 狸猫换太子 下一个节点替我受死。
bool DelPoint(PNode plist,PNode point)//把后面一个节点 给到前面 但不能删除最后一个节点
{
assert(plist!== NULL && point!== NULL);
if(plist == NULL || point == NULL);
return false;
if(point->next == NULL)//删除节点时尾节点 按位置删
{
return Del_pos(plist,Get_length(plist)-1)
}
Node*p=point->next;
point->data=p->data;
point->next=p->next;
free(p);
p = NULL;
return true;
}
第三题 判断两单链表是否相交 有的话将第一个交点返回
两单链表只会存在题目三这种相交
//只判断两个单链表是否相交?
//只要相交 他两的尾巴一定相同 让两个指针都跑到尾节点 比较是否是一个节点即可。
Node*Intersect(PNode plist1,plist2)
{
//assert
int len1=Get_length(plist1);
int len2=Get_length(plist2);//知道长度 让长的先走
Node*p=len1>len2?plist1:plist2
Node*q=len1>len2?plist2:plist1;
for(int i=0;i<abs(len1-len2);i++)//abs求绝对值
{
p = p->next;//代表长的向后跑
}//len相同则不循环
//此时 p q长度一致
while(p!=NULL)//跑到结尾
{
if(p=q)
{
return p;
}
p=p->next;
q=q->next;
}
return NULL;//没相交 返回空
}
第四题 获取单链表倒数第k个节点
PNode GetendK(PNode plist,int k)
{
assert(plist!=NULL && k>0 && k<=getlength(plist));
if(plist=NULL||k<=0||k>Get_length(plist))
return NULL;
Node*p=plist;
Node*q=plist;
for(int i=0;i<k;i++)//倒数第k个 先让p往后走k步
{
p=p->next;
}
while(p!=NULL)//
{
p=p->next;
q=q->next;
}
return q;
}
第五题 两个指针 跑的速度不一样 存在环就会相遇
判断单链表是否存在环 如果存在将入环的点返回
void IsLoop(PNode plis)
{
assert(plist!=NULL);
if(plist==NULL)
return NULL;
//在分别定义一快一慢指针
Node*fast=plist;//快指针 一次走两步
Node*slow=plist;//慢指针 一次走一步
//一直跑 没环 快的先到终点 有环 则遇到
while(1)//死循环
{
if(fast=NULL||fast->next=NULL)//fast第一步为空 或者 走两步为空都代表没有环
{
return NULL;
}
fast = fast->next->next;
slow = slow->next;
if(fast == slow)//有环
{
break ;
}
}
}//死循环三种退出方式 fast第一步为空或者 第二部为空 则代表没有环 ;fast最终追上了slow 则代表有环 两者相遇。
Node*p=plist;
Node*q=fast;//Node*q=slow;
while(p!=q)//从头开始跑 从节点开始跑
{
p=p->next;
q=q->next;
}
return p;