关于链表操作编程实现的一些总结

       链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

       使用链表结构可以克服数组需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。链表有很多种不同的类型,单项链表、双向链表和循环链表。下面总结链表操作的代码实现。

1.单向链表

typedef struct student
{
    int data;
    struct student *next;
} node;

// 创建链表
node *CreateList()
{
    node *head,*rear,*temp;
    head = (node *)malloc(sizeof(node));
    rear = head;
    int flag = 1, x;

    while (flag)
    {
        cout<<"\nPlease input the data:";
        cin>>x;

        if (x != 0)
        {
            temp = (node *)malloc(sizeof(node));
            temp->data = x;
            rear->next = temp;
            rear = temp;
        }
        else
            flag = 0;

    }

    head = head->next;
    rear->next = NULL;

    return head;
}

// 获取链表长度
int GetListLength(node *head)
{
    int count = 0;
    node *temp = head;
    while (temp != NULL)
    {
        count++;
        temp = temp->next;
    }

    return count;
}

// 链表内容输出
void PrintList(node *head)
{
    node *temp = head;
    while (temp != NULL)
    {
        cout<<temp->data<<" ";
        temp = temp->next;
    }

    cout<<endl;
}

// 删除节点
node *DeleteElement(node *head, int num)
{
    node *p1, *p2;
    p1 = head;
    if (p1 != NULL)
    {
        while (num != p1->data && p1->next != NULL)
        {
            p2 = p1;
            p1 = p1->next;
        }

        if (num == p1->data)
        {
            if (p1 == head)
                head = p1->next;
            else
                p2->next = p1->next;
            free(p1);
        }
        else
        {
            cout<<"Can not find the data: "<<num<<endl;
        }
    }
    return head;
}

// 链表逆序输出(递归函数实现)
void ReversePrintList(node *head)
{
    node *temp = head;
    if (temp != NULL)
    {
        if (temp->next != NULL)
        {
            ReversePrintList(temp->next);
        }
        cout<<temp->data<<endl;
    }
}

// 链表逆置
node *ReserveList(node *head)
{
    if (head == NULL || head->next == NULL)
        return head;

    node *t, *p1, *p2, *p;
    p1 = (node *)malloc(sizeof(node));
    p1->data = head->data;
    p1->next = NULL;
    p = p1;
    t = head->next;

    while (t != NULL)
    {
        p2 = (node *)malloc(sizeof(node));
        p2->data = t->data;
        p2->next = p;
        p = p2;
        t = t->next;
    }
    return p2;

}

2.双向链表

typedef struct student
{
    int data;
    struct student *prev;
    struct student *next;
} node;

// 创建链表
node *CreateList()
{
    node *head,*rear,*temp;
    head = (node *)malloc(sizeof(node));
    rear = head;
    int flag = 1, x;

    while (flag)
    {
        cout<<"\nPlease input the data:";
        cin>>x;

        if (x != 0)
        {
            temp = (node *)malloc(sizeof(node));
            temp->data = x;
            rear->next = temp;
            temp->prev = rear;
            rear = temp;
        }
        else
            flag = 0;

    }

    head = head->next;
    head->prev = NULL;
    rear->next = NULL;

    return head;
}
3.循环链表
typedef struct node_str
{
    int data;
    struct node_str *next;

}LNode, *LinkList;

// 创建循环链表(n为循环链表中元素总数)
LinkList CreateCircularList(int n)
{
    LinkList head,rear,temp;
    int id = 1;

    head = (LinkList)malloc(sizeof(LNode));
    head->data = id;
    head->next = head;
    rear = head;

    while (--n)
    {
        temp = (LinkList)malloc(sizeof(LNode));
        temp->data = ++id;
        temp->next = rear->next;
        rear->next = temp;
        rear = temp;
    }
    return head;
}

// 输出循环链表k位置开始的m个元素(k从1开始计算)
void PrintCircularList(LinkList head, int k, int m)
{
    if (head != NULL)
    {
        LinkList newHead = head;
        k--;
        while (k)
        {
            newHead = newHead->next;
            k--;
        }

        for (int i=0; i<m; i++)
        {
            cout<<newHead->data<<endl;
            newHead = newHead->next;
        }
    }
}

循环链表求解约瑟夫问题

// 约瑟夫环(约瑟夫问题):
// 已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,
// 数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复
// 下去,直到圆桌上仅剩1人。


// 约瑟夫问题
void JOSEPHUS(int n, int m, int k)
{
    // 创建循环队列
    LinkList head = CreateCircularList(n);

    // 将队列头移动到编号为k的位置
    k--;
    while (k)
    {
        head = head->next;
        k--;
    }

    // 开始报数,删除节点
    while (n > 1)
    {
        LinkList p = head, temp;
        for (int i=1; i<m; i++)
        {
            p = head;
            head = head->next;
        }
        temp = head;
        p->next = temp->next;
        head = temp->next;
        free(temp);
        n--;
    }

    // 输出最后留下人的编号
    cout<<head->data<<endl;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值