单链表编程考点
1、将单链表的第一个结点放在单链表的最后一个结点的后面
/*
设h是无头结点的单链表,如果线性表h的长度不小于2,则将首元结点删除并插入到表尾
将单链表的第一个结点放在单链表的最后一个结点的后面
*/
typedef struct node
{
elementype data;
struct node *next;
}*linklist;
void change(linklist &h) //linklist &h等价于struct node *&h,这样就可以修改指针h的值;此时不需要return返回已经修改的单链表的值
{
linklist p,q; //linklist p,q等价于struct node *p、struct node *q;
if(h && h->next) //如果链表中有不少于2个结点
{
q = h; //令p指向第1个结点h
h = h->next; //令h指向第2个结点
p = h; //令p指向第2个结点
while(p->next) //第一次循环时,判断第2个结点的指针域是否为空,如果为空则只有两个结点,则不需要找到最后的一个结点,否则一直循环,找到最后一个结点为止
p = p->next; //顺着p开始往下找,一直找到最后一个结点
p->next = q; //将第一个结点接在最后一个结点后面
q->next = NULL; //新的尾结点没有后继,置后继为空
}
}
/*
分析:1、在if判断语句中h为单链表的某一指针指向单链表中的某一个结点
2、q = h;此语句的含义是另外一个指针q与指针h同时指向同一个结点
3、h = h->next;此语句中的h->next所表示的含义是h->next指向单链表中h指针指向的下一个结点,与此同时h指针和h->next指针同时指向该结点
*/
typedef struct node
{
elementype data;
struct node *next;
}*Linklist;
Linklist mynode(LinkList L) //L是不带头结点的单链表的头指针
{
if(L && L->next) //如果链表中有不少于2个结点
{
q = L; //令p指向第1个结点h
L = L->next; //令h指向第2个结点
p = L; //令p指向第2个结点
while(p->next)
p = p->next; //顺着p开始往下找,一直找到最后一个结点
p->next = q; //将第一个结点接在最后一个结点后面
q->next = NULL; //新的尾结点没有后继,置后继为空
}
return L;
}
2、实现单链表的删除算法,删除成功返回1,删除失败返回0
/*实现单链表的删除算法,删除成功返回1,删除失败返回0*/
typedef struct node
{
elementype data;
struct node *next;
}*LinkList, LNode;
int ListDelete(LinkList L, int i, ElemType *s) //s是存储将要删除的值,i是将要被删除元素的指定位置
{
LNode *p,*q; //定义了两个新的指针变量p、q;
int j;
p = L; //p指向L单链表的第一个结点元素
j = 0;
while((p->next != NULL)&&(j < i-1)) //j < i-1此处的判断条件是i-1的原因是当最后一次,不满足条件之前,j的值自动增加了一位
{
p = p->next; //而我们进行删除操作的前提是找到被删除结点元素的前驱结点
j++;
}
if(p->next == NULL || j > i-1)
return 0; //如果if语句成立,将执行return 0;语句,运行过程终止
q=p->next; //否则将q指针指向p->next指针所指的结点,即指向被删除结点元素
*s = q->data;
p->next = q->next; //此语句将指定位置的结点删除,p->next所代表的是被删结点元素的前驱结点的next指针域,而q->next指向被删结点元素的后继结点
free(q); //释放结点占有的存储空间
return 1;
}
3、尾插法建立单链表
//尾插法建立单链表
typedef struct node
{
int data;
struct node *next;
}lklist;
void lklistcreate(lklist *&head ,int n) //n表示单链表的长度
{
lklist *q; //定义一个新的结点指针
for(i = 1;i<=n;i++)
{
p=(lklist *)malloc(sizeof(lklist)); //创建一个新的结点
scanf("%d",&(p->data)); //获取该结点的数值
p->next = NULL;
if(i==1)
head = q = p; //head = q = p;该语句表示头指针head,新的结点指针q都指向结点p;
else
{
q->next = p; //注意:定义的新的结点指针q的作用是通过移动该指针的指向,来实现链表的创建,将q结点的next指针域指向最新创建的结点
q=p; //将结点连接以后,再改变q指针的指向,为下一次新结点的创建作好准备
}
}
}
4、逆转线性单链表,采用是头插法
//逆转线性单链表,采用是头插法
typedef struct node //就地逆置单链表
{
elemtype data;
struct node *next;
}node;
node *Reverse (node *head) //head是带头结点的单链表
{
node *p ,*q;
p = head->next; //p指向第一个元素
head->next=NULL; //保留第一个元素,将头结点的指针域置空
while(p!=NULL) //将原链表的元素用头插法插入新的链表中
{
q=p; //令q指向链表的当前第一个元素
p=p->next; //p指针后移
q->next = head->next; //在新表中插入结点q
head->next = q;
}
return head;
}
5、在带头结点的单链表L中,删除所有值为x的结点
//在带头结点的单链表L中,删除所有值为x的结点
typedef struct LNode
{
Elemtype data;
struct LNode *next;
}LNode, *Linklist;
void delete(Linklist &L ,ElemType x)
{
LNode *q=L;
LNode p=L->next; //初始化p指向第一个结点,q始终指向p结点的前驱
while(p!=NULL)
{
if(p->data == x) //若p指针指向当前结点的值等于x
{
q->next = p->next;
free(p); //删除该结点,并修改p指针
p=q->next; //寻找链表中下一个值为x的结点
}
else
{
q=p;
p=p->next; //先使q后移,p向后移动
}
}
}
6、有序递增序列,删除所有值大于mink且小于maxk的元素
//有序递增序列,删除所有值大于mink且小于maxk的元素
typedef struct node //就地逆置单链表
{
elemtype data;
struct node *next;
}node;
void Delete_Between(node *head, int mink, int maxk)
{
node *p = head, *q;
while(p->next->data <= mink) //p是最后一个不大于mink的元素
p=p->next;
if(p->next) //如果还有比mink更大的元素
{
q=p->next;
while(q->data<maxk) //q是第一个不小于maxk的元素
q=q->next; //while循环结束以后,q指向比maxk值还大的结点元素
p->next = q; //此语句是删除所有值大于mink且小于maxk的元素
}
}
7、将带头结点单链表h1和h2合并成升序排列的单链表
//将带头结点单链表h1和h2合并成升序排列的单链表
typedef struct L
{
int data;
struct L *next;
}LinkL;
LinkL *mergeList(LinkL *h1, LinkL *h2)
{
LinkL *h, *Next, *q;
h=h1;
Next = h;
h1=h1->next; //表h1的第一个结点
h2=h2->next; //表h2的第一个结点
while(h1 != NULL && h2 != NULL) //如果表h1和h2均不为空表
{
if(h1->data <= h2->data) //如果h1指针所指向当前结点的值小于h2
{ //指针所指向的当前结点的值
q=h1; //则令q暂存h1指针所指向的结点
h1=h1->next; //h1指针向后移动
}
else //如果h2指针所指向当前结点的值小于h1
{ //指针所指向的当前结点的值
q=h2; //则令q暂存h2指针所指向的结点
h2-h2->next; //h2指针向后移动
}
Next->next = q; //将指针p所指向的结点接在Next指针所指的结点后面
Next = q;
}
if(h1 == NULL) //如果原h2链表中所有结点已插入但是原h1链表还有结点没插完,则直接把剩余部分接在next指针后面。要是原h1表的所有结点已经全部插完但是h2还有结点没插完,亦是如此
Next->next = h2;
if(h2 == NULL)
Next->next = h1;
return h; //返回新表的指针
}
8、用单链表lc表示集合C,分别将la中的元素取出,再在lb中进行查找,如果在lb中出现,则将其插入到lc中
//将单链表A分解成一个小于零的单链表和大于零的单链表
typedef struct node
{
elemtype data;
struct node *next;
}*LinkList,Linknode;
void decompose(LinkList La,LinkList Lb,LinkList Lc)
{
Linknode *p;
Lc=(Linknode *)malloc(sizeof(Linknode));
Lc->next = NULL; //表C的头结点的next域置空
p=La->next; //令p指向表A的第一个元素结点
Lb=La; //令Lb指向表La
Lb->next = NULL; //令表La的next域置空
while(p) //遍历原表A
{
La=p->next; //令La暂存p结点的后继指针
if(p->data >0) //如果p结点值大于0,则接在表C后面
{
p->next=Lc->next;
Lc->next = p;
}
else{ //如果p结点的值小于0,则接在表B后面
p->next =Lb->next;
Lb->next = p;
}
p=La; //令p指向原p所指向的结点的下一个位置
}
}
9、将单链表A分解成一个小于零的单链表和大于零的单链表
//用单链表lc表示集合C,分别将la中的元素取出,再在lb中进行查找,如果在lb中出现,则将其插入到lc中
typedef struct node
{
elemtype data;
struct node *next;
}*LinkList,LNode;
void interaction(LinkList la, LinkList lb, LinkList &lc)
{
LinkList pa ,pb, pc;
lc = new LNode(); //生成lc的头结点
pc=lc; //pc永远指向lc的尾结点
pa=la->next; //pa指向la的第一个元素
while(pa)
{
pb=lb->next; //pa指向lb表的第一个元素
while(pb && pb->data != pa->data)
pb=pb->next; //在pb中查找元素,使其值等于pa->data
if(pb) //如果存在这样的元素
{
pc->next = new LNode(); //生成lc新的尾结点
pc = pc->next; //pc指向新的尾结点
pc->data= pa->data; //将pa->data复制到pc中
}
pa=pa->next; //继续比较pa表的下一个结点元素
}
pc->next =NULL; //pc为尾结点,pc表比较完成后,置pc后继为空
}
10、已知指针hb和ha分别指向两个单链表的头结点,长度为m和n,假设hc指向连接后的链表的头结点
//已知指针hb和ha分别指向两个单链表的头结点,长度为m和n,假设hc指向连接后的链表的头结点
typedef struct node
{
elemtype data;
struct node *next;
}LinkList;
void ListConcat(LinkList ha, LinkList hb, LinkList *hc)
{
LinkList p; //把链表hb接在ha后面形成链表hc
hc=ha; //由指针p指向ha的尾元结点
while(p->next !=NULL) //查找原ha表的最后一个结点
p=p->next;
p->next = hb->next; //把hb表的第一个元素及其后面元素接在p指针指向的结点后面
free(hb);
}
11、删除单链表中重复的元素
//删除单链表中重复的元素
typedef struct node
{
elemtype data;
struct node *next;
}LinkedList ,*LNode;
LinkedList DeleteSameElement(LinkedList L)
{ //L为递增有序的单链表
LNode u;
LinkedList p, pre;
pre = L->next; //pre指针指向第一个元素结点
p= pre->next; //p指向pre所指结点的后继结点
while(p!=NULL) //如果p指针不为空
if(p->data == pre->data) //p所指结点的值等于pre所指结点的值
{
u=p; //用指针u暂存p指针所指向的结点
p=p->next; //p指针后移
free(u); //释放掉u指针所值结点的内存空间
}
else{ //p和pre两指针所指向的结点值不相等
pre = p; //pre指针后移
p = p->next; //p指针后移
}
}
12、交换单链表中指针p所指结点与其后继结点
//交换单链表中指针p所指结点与其后继结点
typedef struct node
{
elemtype data;
struct node *next;
}*LinkList;
int exchange(Linklist &head,Linklist p )
{
LinkList q=head->next; //q指向第一个元素结点
LinkList pre=head; //pre指向头结点
while(q!=NULL && q!=p) //顺着链表开始查找,一直到q=p
{
pre=q;
q=q->next;
}
if(p->next ==NULL) //退出循环之后,若p无后继,则交换失败
return 0;
else{
q=p->next;
pre->next = q;
p->next = q->next;
q->next = p;
}
return 1;
}
13、设有一个无序单链表
1)找出最小值结点
2)若该数是奇数将与其直接后继结点的数值交换
3)该数值是偶数将直接后继结点删除
/*
设有一个无序单链表
1、找出最小值结点
2、若该数是奇数将与其直接后继结点的数值交换
3、该数值是偶数将直接后继结点删除
*/
typedef struct node
{
elemtype data;
struct node *next;
}LinkList;
void OutputMin(LinkList L)
{
int temp;
LinkList q = L->next; //p指向第一个元素结点
LinkList p= q;
while(q)
{ //找出最小值结点p,并打印p结点数值
if(p->data >q->data)
p=q; //如果发现还有比p指针所指结点的值更小的结点,令p指向该结点,否则q后移
q=q->next;
}
printf("%d",p->data);
if(p->next != NULL) //找到了值最小的结点,若该结点有后继结点
{
if(p->data % 2 == 1) //如果该最小值是奇数,则与其后继结点交换
{
temp=p->data;
p->data =p->next->data;
p->next->data = temp;
}
else //如果该最小值是偶数,则删除其后继结点
{
q=p->next;
p->next = q->next;
free(q);
}
}
}