数据结构之双链表、循环链表和静态链表

1.双链表

只要求掌握思想就可以了,完整代码不必深究。
在这里插入图片描述

这里是图解

在这里插入图片描述

上面已经给出关键代码,下面的代码可能实现的有些粗糙,但还是和单链表一样的逻辑,自己不要太陷入细节。
//双链表的创立和基本的操作
//不带头节点
#include<iostream>
using namespace std;

typedef struct link
{
    struct link* prior;//直接前驱的指针
    int data;
    struct link* next;//直接后继的指针
}*Linklist;

int findnode(Linklist head, int e);
void freenode(Linklist& head);

//初始化数据,这里为了表示简单一点就不带头节点,head=NULL判空
//这里用return的方式,不用引用了
Linklist create(Linklist head) {
    head = (Linklist)malloc(sizeof(link));//初始画头节点
    head->data = 1;
    head->next = NULL;
    head->prior = NULL;

    link*temp = head;//创建临时指针
    for (int i = 2; i < 6; i++) {
        link* body = (link*)malloc(sizeof(link));
        body->next = NULL;
        body->data = i;
        body->prior = temp;//连前驱
        temp->next = body;//将前面的next指向新建的
        temp = temp->next;//temp更新
    }

    return head;
}


//打印函数
void printList(Linklist head) {
    link* current = head;
    while (current) {
        std::cout << current->data << " -> ";
        current = current->next;
    }
    std::cout << "nullptr" << std::endl;
}

//释放链表
void freenode(Linklist& head) {
    Linklist temp = head;
    while (temp)
    {
        head = head->next;
        free(temp);
        temp = head;
    }
}


// insert data
Linklist insertlink(Linklist head, int e, int add) {
    Linklist temp = head;//临时变量
    Linklist newnode = (Linklist)malloc(sizeof(link));
    newnode->data = e;
    newnode->next = NULL;
    newnode->prior = NULL;
    if (add == 1) {   //1.   insert  in head node
        newnode->next = head;
        head->prior = temp;
        head = temp;
    }
    else {
        //find where position insert in
        for (int i = 1; i < add - 1; i++) {//find insert's position 's last position
            temp = temp->next;
            if (!temp)//find the final node but node is not exist
            {
                cout << "false" << endl;
                return head;
            }
        }
        if (temp && temp->next == NULL) {//2.  insert in the final position
            temp->next = newnode;
            newnode->prior = temp;
        }
        else {//3.  insert in the middle position 
            newnode->next = temp->next;
            temp->next->prior = newnode;
            temp->next = newnode;
            newnode->prior = temp;
        }
    }
    return head;

}

//delete data
Linklist deletelink(Linklist head, int e) {
    Linklist temp = head;
    while (temp) {
        if (temp->data == e) {//1.delete first node
            if (temp->prior == NULL) {
                head = temp->next;
                if (head) { head->prior = NULL; }


                temp->next = NULL;
                freenode(temp);
                return head;
            }
            if (temp->next && temp->prior) {//2.delete middle node
                temp->prior->next = temp->next;
                temp->next->prior = temp->prior;

                temp->next = NULL;
                temp->prior = NULL;
                freenode(temp);
                return head;
            }
            if (temp->next == NULL)//3.delete last node
            {
                temp->prior->next = NULL;

                temp->prior = NULL;
                freenode(temp);
                return head;
            }

        }
        temp = temp->next;

    }
    cout << "delete false" << endl;
    return head;//false
}

//按值查找find node
int findnode(Linklist head, int e) {
    Linklist temp = head;
    int i = 1;
    while (temp) {
        if (temp->data == e) {
            return i;
        }
        i++;
        temp = temp->next;
    }
    return -1;
}

//update node
void  updatenode(Linklist head, int oldnode, int newnode)
{
    int find = 0;
    Linklist temp = head;
    while (temp) {
        if (temp->data == oldnode) {
            find = 1;
            break;

        }
        temp = temp->next;
    }
    if (find == 1) {

        temp->data = newnode;
        cout << "update ok " << endl;
    }
    else {
        cout << "update false" << endl;

    }
}


void test01() {
    Linklist head = NULL;
    head = create(head);
    cout << "创建好的链表为" << endl;
    printList(head);
    cout << endl;

    cout << "在第三个位置添加一个数字8" << endl;
    head = insertlink(head, 8, 3);
    printList(head);
    cout << endl;


    cout << "将元素4删除" << endl;
    head = deletelink(head, 4);
    printList(head);
    cout << endl;
    //display(head);

    cout << "元素3的位置为" << findnode(head, 3)<<endl<<endl;
    


    cout << "将数字5变为数字9" << endl;
    updatenode(head, 5, 9);
    printList(head);
    cout << endl;
    free(head);
}
int main() {
    test01();
    system("pause");

    return 0;

}

在这里插入图片描述

2.循环链表

在这里插入图片描述

实现约瑟夫环
//循环链表----实现约瑟夫

#include<iostream>
using namespace std;

typedef struct node {
    int num;
    struct node* next;
}*linklist;

//初始化循环链表 
//这里的实现不带头节点
linklist initlist(linklist head) {
    head = (linklist)malloc(sizeof(node));
    head->num = 1;
    head->next = NULL;

    linklist temp = head;
    for (int i = 2; i <= 8; i++) {
        linklist body = (linklist)malloc(sizeof(node));
        body->num = i;
        body->next = NULL;
        temp->next = body;
        temp = temp->next;
    }
    temp->next = head;
    return head;
}

//约瑟夫环
void findwin(linklist head, int k, int m)//k代表报数的位置,m代表报到m出列
{
    linklist temp = head;
    //find num of k,temp是位置的节点
    while (temp->num != k) {
        temp = temp->next;
    }

    //prenode是k位置的上一个节点
      //find winner
    linklist prenode = NULL;
    while (temp->next != temp) {

        for (int i = 1; i < m; i++) {
            prenode = temp;找到出列的人前面一个节点
            temp = temp->next;
        }

        //删除
        prenode->next = temp->next;
        cout << "出列的人的编号为" << temp->num << endl;       
        //free(temp);
        temp = prenode->next;
    }
    cout << "出列的人的编号为" << temp->num << endl;
    //free(temp);

}


void test01() {

    int n = 0, k = 0, m = 0;
    linklist head = NULL;
    cout << "输入圆桌上的人数:" << endl;
    cin >> n;
    head = initlist(head);
    cout << "从第几个人开始报数" << endl;
    cin >> k;
    cout << "数到几的人出列:" << endl;
    cin >> m;
    findwin(head, k, m);
}
int main() {
    test01();
    system("pause");
    return 0;
}

在这里插入图片描述

静态链表

在这里插入图片描述
静态链表的设计初衷是为了在数组环境中模拟链表的一些特性,特别是链表在插入和删除操作上的高效性(不需要移动大量元素),同时尽可能地利用数组的空间连续性和随机访问的优点。

//静态链表
//静态链表不仅能快速地找到数据又能够快速地添加和删除数据
//静态链表使用数组模拟链表
#include<iostream>
using namespace std;
#define maxsize 10
typedef struct arraylist {
    int data;
    int cur;
}*arraylink;
void link1(arraylink array);
int mallocsapce(arraylink array);
int initarray(arraylink array);
//创建备用链表
void link1(arraylink array)
{
    int i = 0;
    for (i = 0; i < maxsize - 1; i++) {
        array[i].cur = i + 1;
        array[i].data = 0;
    }
    array[maxsize - 1].cur = 0;
    array[maxsize - 1].data = 0;
}
//提取空闲空间
int mallocsapce(arraylink array) {
    int a = array[0].cur;//保存空闲节点
    if (array[0].cur) {
        array[0].cur = array[a].cur;//第一个节点指向分配的节点下一位节点,如果是最后一位节点那么则第一个节点的cur为0
    }
    return a;
}
int initarray(arraylink array) {

    link1(array);
    //创建首元节点
    int first = mallocsapce(array);
    array[first].data = 1;
    array[first].cur = 0;
    int temp = first;//temp作为数组“指针”指向链表最后一个
    for (int i = 2; i < 6; i++) {
        int j = mallocsapce(array);//创建新节点
        array[j].data = i;//初始化新节点
        array[temp].cur = j;//将新节点连接到链表中
        temp = j;//temp仍然指向最后一个
    }
    array[temp].cur = 0;//新链表的cur为0

    return first;//因为初始化相当于都是基于first节点而来的,所以要返回first

}
void display(arraylink array, int first) {//要用到这两个参数
    int tempBody = first;//tempBody准备做遍历使用
    while (array[tempBody].cur) {//假设只有三个数据节点,那么在tempBody=3时显然cur为0,循环结束
        printf("%d,%d\n", array[tempBody].data, array[tempBody].cur);
        tempBody = array[tempBody].cur;
    }
    printf("%d,%d\n", array[tempBody].data, array[tempBody].cur);

}


void test01() {
    arraylist array[maxsize];
    int first = initarray(array);
    display(array, first);
}
int main() {

    test01();
    system("pause");
    return 0;
}

在这里插入图片描述

顺序表和链表对比

在这里插入图片描述
在这里插入图片描述

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值