七、线性表(4)

来源:互联网 发布:东北师大网络教育学院 编辑:程序博客网 时间:2024/04/29 15:19

循环链表

1、定义
将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表成为单循环链表,简称循环链表。

这里写图片描述
实现代码分为四部分:
初始化、插入、删除、返回结点所在位置。

2、约瑟夫问题
据说著名犹太历史学家约瑟夫有过以下的故事:
在罗马人占领桥塔帕特后,41个犹太人决定了一个自杀方式,41个人排成一个圆圈,由第一个人开始报数,每报数到第3人,该人就必须自杀,然后再由下一个人重新报数,直到所有人都自杀身亡为止。

代码:用循环链表模拟约瑟夫问题,把41个人自杀的顺序编号输出。

//n个人围圈报数,报m出列,最后剩下的是几号?#include <stdio.h>#include <stdlib.h>typedef strue node {    int data;//数据    struct node *next;//指向下一个位置的指针}node;node *create(int n)//创建链表{    node *p=NULL,*head;    head=(node*)malloc(sizeof(node));//定义头结点    p=head;//p是指向当前结点的指针    node *s;    int i=1;    if(0!=n)    {        while(i<=n)        {            s=(node *)malloc(sizeof(node));            s->data=i++;//为循环链表初始化,第一个结点为1,第二个结点为2.            p->next=s;            p=s;        }        s->next=head->next;//最后一个结点指向第一个结点    }free(head);//释放头结点return s->next;//返回指向头结点的地址}int main(){    int n=41;    int m=3;    int i;    node *p=create(n);//p是指向循环链表第一个结点的指针    node *temp;//临时指针    m%=n;    while(p!=p->next)//不是空表的时候循环    {        for(i=1;i<m-1;i++)        {            p=p->next;        }        printf("%d->",p->next->data);        temp=p->next;//删除第m个结点        p->next=temp->next;        free(temp);        p=p->next;    }    printf("&d\n",p->data);    return 0;}

循环链表的特点
判断是否为空链表的条件:即判断rear是否等于rear->next。
循环链表的特点是无须增加存储量,仅对链接方式稍作改变,即可使得表处理更加方便灵活。

实现将两个线性表(a1,a2,….,an)和(b1,b2,…,bm)连接成一个线性表(a1,a2,….,an,b1,b2,…,bm)的运算。

//假设A,B为非空循环链表的尾指针LinkList Connect(LinkList A,LinkList B){    LinkList p=A->next;//保存A表的头结点位置    A->next=B->next->next;//B表的开始结点链接到A表尾    free(B->next);//释放B表的头结点    B->next=p;    return B;//返回新循环链表的尾指针}

判断单链表中是否有环
有环的定义是,链表的尾结点指向了链表中的某个节点。
判断:

  • 方法一:使用p,q两个指针,p总是向前走,但q每次都是从头开始走,对于每个节点,看p走的步数是否和q一样。
  • 方法二:使用p,q两个指针,p每次向前走一步,q每次向前走两步,若在某个时候p==q,则存在环。
    3、魔术师发牌问题
    问题描述:
    魔术师利用一副牌中的13张黑牌,预先将他们排好后叠放在一起,牌面朝下。对观众说:我不看牌,只数数就可以猜到每张牌是什么,我大声叔叔,你们听,不信?现场演示。
    魔术师将最上面的那张牌数为1,把它翻过来正好是黑桃A,将黑桃A放在桌子上,第二次数1,2,将第一张牌放在这些牌的下面,将第二张牌翻过来,正好是黑桃2,也将他放在桌子上这样依次进行将13张牌全部翻出,准确无误。
    请问:牌的开始顺序是如何安排的?
    代码:
#include <stdio.h>#include <stdlib.h>#define CardNumber 13typedef struct node {    int data;    struct node *next;}sqlist,*linklist;linklist CreatLinkList(){    linklist head=NULL;    linklist s,r;    int i;    r=head;    for(i=1;i<=CardNumber;i++)    {        s=(linklist)malloc(sizeof(sqlist));        s->data=0;        if(head==NULL)            head=s;            else            r->next=s;            r=s;    }    r->next=head;    return head;}//发牌顺序计算void Magician(linklist head){    linklist p;    int j;    int Countnumber=2;    p=head;    p->data=1;    while(1)    {        for(j=0;j<Countnumber;j++)        {            p=p->next;            if(p->data!=0)            {                p->next;                j--;            }        }        if(p->data==0)        {            p->data=Countnumber;            Countnumber++;            if(Countnumber==14)            break;        }    }} //销毁void DestoryList(linklist *list){    linklist ptr=*list;    linklist buff[CardNumber];    int i=0;    while (i<CardNumber)    {        buff[i++]=ptr;        ptr=ptr->next;    }    for(i=0;i<CardNumber;++i)    free(buff[i]);    *list=0;} int main(){    linklist p;    int i;    p=CreatLinkList();    Magician(p);    printf("按如下顺序排列:\n");    for(i=0;i<CardNumber;i++)    {        printf("黑桃%d",p->data);        p=p->next;    }    DestoryList(&p);    return 0;}

双向链表

typedef struct DualNode{    ElemType data;    struct DualNode *prior;//前驱结点    struct DualNode *next;//后继结点}DualNode, *DuLinkList;

对于双向链表中的某一个结点P,它的后继结点的前驱结点是他自己。
双向链表的插入操作
代码实现:

  • s->next=p;
  • s->prior=p->prior;
  • p->prior->next=s;
  • p->prior=s;

双向链表的删除操作

  • p->prior->next=p->next;
  • p->next->prior=p->prior;
  • free(p);
  • 双向链表相对于单链表来说更复杂,每个结点多了一个prior指针。不过,双向链表可以提高算法的时间性能,即用空间来换取时间。

双向循环链表实践

要求实现用户输入一个数使得26个字母的排列发生变化,例如用户输入3,输出结果:
-DEFGHIJKLMNOPQRSTUVWXYZABC
同时需要支持负数,例如用户输入-3,输出结果:
-XYZABCDEFGHIJKLMNOPQRSTUVW

#include <stdio.h>#include <stdlib.h>#define OK   1#define ERROR    0typedef char ElemType;typedef int Status;typedef struct DualNode{    ElemType data;    struct DualNode *prior;    struct DualNode *next;}DualNode,*DuLinkList;Status InitList(DuLinkList *L){    DualNode *p,*q;    int i;    *L=(DuLinkList)malloc(sizeof(DualNode));    if(!(*L))    {        return ERROR;    }    (*L)->next=(*L)->prior=NULL;    p=(*L);    for(i=0;i<26;i++)    {        q=(DualNode *)malloc(sizeof(DualNode));        if(!q)        {            return ERROR;        }         q->data='A'+i;        q->prior=p;        q->next=p->next;        p->next=q;        p=q;    }    p->next=(*L)->next;    (*L)->next->prior=p;    return OK;}void Caesar(DuLinkList *L,int i){    if(i>0)    {        do        {            (*L)=(*L)->next;        }while (--i);    }    if(i<0)    {        do        {            (*L)=(*L)->next;        }while(++i);    }}int main(){    DuLinkList L;    int i,n;    InitList(&L);    printf("请输入一个整数:");    scanf("%d",&n);    printf("\n");    Caesar(&L,n);    for(i=0;i<26;i++)    {        L=L->next;        printf("%c",L->data);    }    printf("\n");    return 0;} 
0 0
原创粉丝点击