七、线性表(4)

原创 2016年08月31日 13:32:37

循环链表

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 13

typedef 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    0

typedef 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;
} 
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

数据结构线性表.SWF(4)

  • 2011年08月14日 09:56
  • 25KB
  • 下载

线性表4--一元多项式相加

一元多项式 Pn(x)=amX^em + am-1X^em-1 +...+ a0X^e0 对于非零系数的项,来构成单链表,每个节点的数据域包含系数和指数两部分,如图              q...

大话数据结构4线性表(续1)

1、顺序存储结构的插入与删除:    获得元素操作: #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 ty...

数据结构学习笔记(4.线性表之双向链表)

本节知识点: 1.为什么选择双向链表:因为单向链表只能一直指向下一个链表元素,不能获得前一个元素,如果要进行逆序访问操作是极其耗时的,所以引入双向链表。 2.双向链表的结构:在单向链表的基础上增加...

线性表的应用4(链表节点的移动)

对单链表,编写算法实现以第一个元素为基准,将小于该元素的节点全部放到前面,大于该节点的元素全部放到后面。时间复杂度要求为O(n),不能申请新空间。 算法分析: 用两根指针实现的移动,由于是单链表,...
  • PNAN222
  • PNAN222
  • 2016年04月06日 13:37
  • 228

数据结构(4)-线性表(循环链表)

概念:将单链表终端节点的指针由空指针改为指向头结点,就使整个单链表形成一个环,这种首尾相接的单链表称为单循环链表,简称循环链表; 循环链表和单链表的区别:尾结点的指针不指向null,而是指向head...

数据结构(4)--循环链表的应用之约瑟夫环问题以及线性表总结之顺序表与链表的比较

参考书籍:数据结构(C语言版) 严蔚敏 吴伟民编著 清华大学出版社 1.循环链表应用--约瑟夫环问题 1.1问题说明     问题描述:编号为1,2,···,n的n个人围坐在一圆桌旁,每人持有一个正整...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:七、线性表(4)
举报原因:
原因补充:

(最多只允许输入30个字)