这周的一点总结

  这周开始我就开始学习数据结构了,数据结构好难啊,显示讲什么是数据结构,然后讲 时间复杂度,顺序表,链表,顺序栈,链栈,顺序循环队列,链式队列,暂时只讲了这么多,后面还有树跟哈希表下周再上,等我上完过后再来讲这两个,下面我i将仔细地讲讲我这周上过的。

  为什么学习数据结构:为了提高程序的运行效率

什么是数据:是对事物进行的记录并可以鉴别的符号,对我们有用的信息都可以成为数据。

什么是结构:指元素(数据)的相互关联和相互作用的关系。

根据数据元素之间的关系,分成4个基本结构:

  • 集合:结构中的数据是在同属空间内,没有其它关系,比如刚入学的学生。

  • 线性结构:数据为一一对应的关系,比如已分发学号的学生shijianfuzhadu ,图书馆的图书。

  • 树状结构(层次关系):数据为一对多的关系,家族的族谱,公司的架构。

  • 图状结构(网状结构):数据为多对多的关系,城市与城市之间的交通干线。

算法:算法分析是指在正常程序工作之下,对齐优略分析。

时间复杂度:描述程序运行的时间复杂度BigO即大O表示法,计算的是程序运行的次数而不是程序运行的时间,时间复杂度 = 程序运行的次数。

公式: T(n) = O(f(n))
T(n) : 表示算法的渐进时间复杂度
f(n) : 程序运行的次数
O : 表示正比关系

常用的时间复杂度:

1.常数阶O(1)
int a = 1;
int b = a;
2.对数阶O(logN)==》2^k = N ==> K = logN,k为程序运行的次数
int i = 1;
while(i < n)
i = 2*i;
3.线性阶O(N)
for(int i = 1; i <= n; i++)
x++
4.线性对数阶O(NlogN)
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <=n; j+=i)
{
x++;
}
}

5.平方阶(n^2)
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
x++;
}

 一个小练习

计算过下列的时间复杂度:

1.

for(int i = 1; i <= n; i=i*2)
{
printf("%d\t",i);
}

 2^i = n ===>i = logN

2.

int i = 0;
int s = 0;
while(s < n)
{
++i;
s+=i;
}

 1+2+3+...+k = k(k+1)/2==>k^2+k=2n==>因为k和2是常量,忽略==>k^2=n==>k=根号n

线性表

概念:一对一的数据所组成的关系称为线性表,注意线性是逻辑结构.

特点:

(1) 存在唯一的一个被称为"第一个"的数据元素。

(2) 存在唯一的一个被称为"最后一个"的数据元素。

(3) 除了第一个外,集合中每一个数据元素只有一个前驱节点。

(4) 除了最后一个外,集合中每个数据元素均只有一个后驱节点。

注意:

1.线性表是一种数据内部的逻辑关系,与存储形式无关。

2.线性表既可以采用连续的顺序存储(数组),也可以采用离散的链式存储(链表)。

3.顺序表和链表都称为线性表。

顺序表

概念:顺序存储的线性表。

基本操作:我用代码来表示

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

typedef struct  sequenList
{
    int cap;   // 顺序表总大小
    int last;  // 顺序表元素下标
    int *data; // 指向顺序表的首元素地址
}sequenList;

//初始化表
sequenList *init_seque(int cap)
{
    if(cap <= 0)
        return NULL;
    //给顺序管理结构体分配空间
    sequenList *head = malloc(sizeof(sequenList));
    if(head == NULL)
        return NULL;
    head->cap = cap;
    head->last = -1;
    head->data = calloc(cap,sizeof(int));
    if(head->data == NULL)
        return NULL;

    return head;
}

//判断表是否满
bool isFull(sequenList *head)
{
    if(head->cap == head->last + 1)
        return true;
    return false;
}

//插入数据
bool insert(sequenList *head, int data)
{
    if(head == NULL)
        return false;
    //判断数据是否已满
    if(isFull(head))
        return false;
   
    head->data[++head->last] = data;
    return true;
}

//判断表为空
bool isEmpty(sequenList *head)
{
    if(head->last == -1)
        return true;
   
    return false;
}

//显示插入数据
void showList(sequenList *head)
{
    if(isEmpty(head))
        return;
    for(int i = 0; i < head->last+1; i++)
    {
        printf("%d\t", head->data[i]);
    }
    printf("\n");

}

//删除数据
bool removeData(sequenList *head, int data)
{
    if(isEmpty(head))
        return false;
    //寻找要删除的内容
    int i = 0;
    while(i <= head->last)
    {
        if(head->data[i] == data)
        {
            //找到需要的数据,使其后面的数据覆盖他
            for(int j = i; j < head->last ;j++)
            {
                head->data[j] = head->data[j + 1];
            }
            i = -1;
            head->last--;
        }
        i++;
        //printf("data = %d\t\n", head->data[i]);
    }
    if(i == head->last)
        return true;  
   
    return true;
}

//销毁顺序表
void destroy(sequenList *head)
{
    if(head == NULL)
        return;
    free(head->data);
    free(head);
}

//排序
void bubble(sequenList *head)
{
    for(int i = 0; i < head->last; i++)
    {
        for(int j = 0; j < head->last - i; j++)
        {
            if(head->data[j] > head->data[j + 1])
            {
                int temp = head->data[j];
                head->data[j] = head->data[j + 1];
                head->data[j + 1] = temp;
            }
        }
    }
}

int main(int argc, char const *argv[])
{
    int count = 0;
    //初始化表
    sequenList *head = init_seque(10);
    if(head == NULL)
    {
        printf("init failed\n");
        return -1;
    }

    printf("请输入数据\n");
    for(int i = 0; i < 7; i++)
    {
        int data;
        scanf("%d", &data);
       
        //将输入插入到表
        insert(head,data);
    }

    bubble(head);

    for(int i = 0; i < head->last; i++)
    {
        if( head->data[i] < 0)
        {  
            //head->data[i] = ~(head->data[i] -1);
            removeData(head,-head->data[i]);
            removeData(head,head->data[i]);
            i--;          
        }
    }
    //显示
    showList(head);

    destroy(head);
    return 0;
}
顺序表的优缺点
优点:

不需要多余的信息来记录数据的关系,存储密度高。

所有数据顺序存储在一片连续的内存中,支持立即访问任意一个随机数 据,比如上述顺序表中第i个节点是s->data。

缺点:

插入、删除时需要保持数据的物理位置反映其逻辑关系,需要成片移动数据。

当数据节点较多时,需要一整片较大的连续内存空间。

当数据节点数量变化剧烈时,内存的释放和分配不灵活。

 

链式表与顺序表类似,但也有差异:
  既然顺序存储中的数据因为挤在一起而导致需要成片移动,那很容易想到的解决方案是将数据离散地存储在不同内存块中,然后在用来指针将它们串起来。这种朴素的思路所形成的链式线性表,就是所谓的链表。
 
链表的分类:单向链表与双向链表,循环链表,有头结点的单向链表与无头结点的单向链表。
下面我将用代码来展示这些不同的链表
无头结点的单向链表;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef int dataType;

// 节点
struct node
{
    dataType data;// 指针域
    struct node *next; // 指向下一个节点
};

// 创建新节点
struct node *create_newNode(dataType data)
{
    struct node *pnew = malloc(sizeof(struct node));
    if(pnew == NULL)
        return NULL;

    pnew->data = data;
    pnew->next = NULL;
    return pnew;
}

// 创建链表
struct node *create_list(void)
{
    // 设置空链表
    struct node *head = NULL;
    struct node *tail = NULL;
    while(1)
    {
        dataType data;
        if(scanf("%d",&data) == 0)
            break;
        // 创建新节点
        struct node *pnew = create_newNode(data);
        if(pnew == NULL)
        {
            printf("create new node failed:\n");
            //exit(0); // 不管再哪里调用,整个程序结束
            return NULL; // 只退出本函数
        }
        // 从无到有
        if(head == NULL)
        {
            head = pnew;
            tail = pnew;
        }
        else// 从少到多
        {
            // 尾插法
            //tail->next = pnew;
            //tail = pnew;
            // 头插法
            pnew->next = head;
            head = pnew;
        }
    }

    return head;
}

//增加节点
struct node *insertNode(struct node** head, int position, int data)
{
    // 创建新节点
    struct node* newNode = (struct node*)malloc(sizeof(struct node));
    newNode->data = data;
    newNode->next = NULL;

    // 如果要插入的位置是链表的头部
    if (position == 0)
    {
        newNode->next = *head;
        *head = newNode;
        return 0;
    }
    // 找到要插入位置的前一个节点
    struct node *current = *head;
    for (int i = 0; i < position - 1 && current != NULL; i++)
    {
        current = current->next;
    }

    // 如果找到了要插入位置的前一个节点
    if (current != NULL)
    {
        newNode->next = current->next;
        current->next = newNode;
    }
    else
    {
        printf("Invalid position\n");
    }
}

// 显示链表
void show_list(struct node *head)
{
    if(head == NULL)
        return;

    for(struct node *p = head; p != NULL; p = p->next)
    {
        printf("%d\t",p->data);
    }
    printf("\n");
}

//修改节点
void revise_node(struct node *head, dataType data)
{
    while(1)
    {
        if(head->data != data && head->next != NULL)
        {
            head = head->next;
        }
        else if(head->data == data)
        {
            head->data = 3;
            break;
        }
        else
        {
            break;
        }
    }
}

//删除节点
struct node *removed(struct node *head, int data)
{
    struct node *p = head;
    if(head->data == data)
    {
        head = head->next;
    }
    while(p->next != NULL)
    {
        if(p->next->data == data)
        {
            p->next = p->next->next;
        }
        p = p->next;
    }
    return head;
}


int main(int argc, char const *argv[])
{
    // 创建链表
    struct node *head = create_list();
    if(head == NULL)
        return -1;
   
    //修改节点
    //revise_node(head, 8);
    //删除节点
    head = removed(head, 5);
    //增加节点
    //insertNode(&head,3,5);
    // 显示链表
    show_list(head);
    return 0;
}
有头结点的单向链表
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef int dataType;

//数据节点
struct node
{
    dataType data;
    struct node *next;
};

//头节点,管理结构体
struct headNode
{
    struct node *first; //指向头节点
    struct node *tail; //指向尾节点
    int nodeNumber;     //链表节点个数
};

struct headNode *init_headNode(void)
{
    struct headNode *head = malloc(sizeof(struct headNode));
    if(head == NULL)
        return NULL;
   
    head->first = NULL;
    head->tail = NULL;
    head->nodeNumber = 0;

    return head;
}

//创建新节点
struct node *creat_newNode(dataType data)
{
    struct node *pnew = malloc(sizeof(struct node));
    if(pnew == NULL)
        return NULL;
   
    pnew->data = data;
    pnew->next = NULL;

    return pnew;
}

//创建带头节点的单向链表
struct headNode *creat_list(void)
{
    //初始化管理结构体
    struct headNode *head = init_headNode();
    if(head == NULL)
        return NULL;
   
    while(1)
    {
        dataType data;
        if(scanf("%d", &data) == 0)//退出
            break;
       
        //创建新节点
        struct node *pnew = creat_newNode(data);
        //从无到有
        if(head->first == NULL)
        {
            head->first = pnew;
            head->tail = pnew;
        }
        else //从少到多
        {
            //头插法
            //pnew->next = head->first;
            //head->first = pnew;
           
            //尾插法
            head->tail->next = pnew;
            head->tail = pnew;
           
        }
        //新增节点
        head->nodeNumber++;
    }
    return head;
}
//更新节点
struct headNode *updata_node(struct headNode *head,dataType newData,dataType data)
{
    //找节点
    struct node *p = head->first;
    while(p)
    {
        if(p->data == data)
        {
            p->data = newData;
            break;
        }
        else//继续找
        {
            p = p->next;
        }
    }
    if(p == NULL)
    {
        printf("没有需要替换的数据\n");
    }
    return head;
}

//添加节点
struct headNode *add_node(struct headNode *head,dataType newData,dataType data)
{
    //创建新节点
    struct node *pnew = creat_newNode(newData);
    if(pnew == NULL)
        return NULL;
   
    //找位置
    struct node *p = head->first; //遍历指针
    struct node *pre = NULL;      //p的前驱指针

    while(p)
    {
        if(p->data == data)
        {
            break;
        }
        else
        {
            pre = p;
            p = p->next;
        }
    }
    //找不到,尾插
    if(p == NULL)
    {
        head->tail->next = pnew;
        head->tail = pnew;
    }
    else if(head->first->data == p->data)//头插
    {
        pnew->next = head->first;
        head->first = pnew;
    }
    else//中间
    {
        pnew->next = p;
        pre->next = pnew;
    }
    //更新节点数
    head->nodeNumber++;
   
    return head;
}

//删除节点
struct headNode *remove_node(struct headNode *head,dataType data)
{
    //找节点
    struct node *p = head->first; //遍历指针
    struct node *pre = NULL;

    while(p)
    {
        if(p->data == data)
        {
            break;
        }
        else
        {
            pre = p;
            p = p->next;
        }
    }
        if(p == NULL)//找不到
        {
            printf("没有需要删除的节点\n");
            return head;
        }
        if(p == head->first)//首节点
        {
            head->first = p->next;
            p->next = NULL;
            free(p);
        }
        else if(p == head->tail)//尾节点
        {
            head->tail = pre->next;
            pre->next = NULL;
            free(p);
        }
        else//中间
        {
            pre->next = p->next;
            p->next = NULL;
            free(p);
        }
        //更新链表个数
        head->nodeNumber--;

    return head;
}

//判断链表是否为空
bool isEmpty(struct headNode *head)
{
    if(head->nodeNumber == 0)
        return true;

    return false;
}

//销毁链表
void destroy_list(struct headNode *head)
{
    if(isEmpty(head))
    {
        return ;
    }

    struct node *tmp = NULL;
    for(struct node *p = head->first; p != NULL; p = tmp)
    {
        tmp = p->next;
        p->next = NULL;
        free(p);
        head->nodeNumber--;
    }
}

//链表逆序
struct headNode *reverse_list(struct headNode *head)
{
    //指向首节点
    struct node *p = head->first;
    //指向拆下来的节点
    struct node *pnew = NULL;

    //拆头节点
    head->first = NULL;
    head->tail = NULL;

    //头插法插入拆下来的节点
    while(p)
    {
        pnew = p;
        p = p->next;
        //断开pnew
        pnew->next = NULL;

        if(head->first = NULL)
        {
            head->first = pnew;
            head->tail = pnew;
        }
        else
        {
            //头插法
            pnew->next = head->first;
            head->first = pnew;
        }
    }
}
//显示链表
void show_list(struct headNode *head)
{
    if(isEmpty(head))
        return;

    for(struct node *p = head->first; p != NULL; p = p->next)
    {
        printf("%d\t", p->data);
    }
    printf("\n");

    printf("链表已有%d个节点", head->nodeNumber);
}

int main(int argc, char const *argv[])
{
    //创建链表
    struct headNode *head = creat_list();
    if(head == NULL)
        return -1;

    //更新节点
    //head = updata_node(head,8,8);

    //添加节点
    //head = add_node(head,3,3);

    //删除节点
    //head = remove_node(head,3);
 
    //显示
    show_list(head);

    //销毁链表
    destroy_list(head);
    return 0;
}
双向链表
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

typedef int dataType;

//节点
struct node
{
    dataType data;
    struct node *per;//指向上一个节点
    struct node *next;//指向下一个节点
};

//创建头节点,管理结构体
struct headNode
{
    struct node *first;//指向头节点
    struct node *tail;//指向尾节点
    dataType nodeNumbre;//记录节点数
};

//初始化管理结构体
struct headNode *init_headNode()
{
    struct headNode *head = malloc(sizeof(struct headNode));
    if(head == NULL)
        return NULL;
   
    head->first = NULL;
    head->tail = NULL;
    head->nodeNumbre = 0;
}
//创建新节点
struct node *creat_newNode(dataType data)
{
    struct node *pnew = malloc(sizeof(struct node));
    if(pnew == NULL)
        return NULL;
   
    pnew->next = NULL;
    pnew->per = NULL;
    pnew->data = data;

    return pnew;
}

//尾插法
struct headNode *addTail()
{

}
//创建链表
struct headNode *creat_list(void)
{
    //初始化管理结构体
    struct headNode *head = init_headNode();
    if(head ==  NULL)
        return NULL;

    while(1)
    {
        dataType data;
        if(scanf("%d", &data) == 0)
            break;
       
        //创建新节点
        struct node *pnew = creat_newNode(data);
        if(head->first == NULL)//从无到有
        {
            head->first = pnew;
            head->tail = pnew;
        }
        else//从少到多
        {
            //头插法
            pnew->next = head->first;
            pnew->per = head->first->per;
            head->first->per = pnew;
            head->first = pnew;
            //尾插法
            //pnew->per = head->tail;
            //head->tail->next = pnew;
            //head->tail = pnew;
        }
        head->nodeNumbre++;
    }
   

    return head;
}

//修改节点
struct headNode *updata_Node(struct headNode *head, dataType data, dataType newData)
{
    struct node *p = head->first;
    while(p)
    {
        if(p->data == data)
        {
            p->data = newData;
            break;
        }
        else
        {
           p = p->next;
        }
    }
    if(p ==  NULL)
    {
        printf("没有找到\n");
    }
    return head;
}
//增加节点
struct headNode *addNode(struct headNode *head, dataType data, dataType newData)
{
    struct node *pnew = creat_newNode(newData);
    struct node *p = head->first;
    if(pnew == NULL)
        return NULL;
   
    while(p)
    {
        if(p->data == data)
        {
            break;
        }
        else
        {
            p = p->next;
        }
    }
        if(p == head->first)
        {
            pnew->next = head->first;
            pnew->per = head->first->per;
            head->first->per = pnew;
            head->first = pnew;
        }

        if(p == NULL)
        {
            pnew->per = head->tail;
            head->tail->next = pnew;
            head->tail = pnew;
        }
        else
        {
            pnew->next = p;
            pnew->per = p->per;
            p->per->next = pnew;
            p->per = pnew;
        }
   
    head->nodeNumbre++;
    return head;
}

//删除节点
struct headNode *removeNode(struct headNode *head, dataType data)
{
    struct node *p = head->first;
    while(p)
    {
        if(p->data == data)
        {
            break;
        }
        else
        {
            p = p->next;
        }
    }
    if(p == NULL)
    {
        printf("没有要删除的节点\n");
        return head;
    }

    if(p == head->first)
    {
        head->first = p->next;
        p->next->per = head->first;
        p->next = NULL;
        p->per = NULL;
        free(p);
    }

    else if(p == head->tail)
    {
        head->tail = p->per;
        p->per->next = NULL;
        p->next = NULL;
        free(p);
    }
    else
    {
        p->next->per = p->per;
        p->per->next = p->next;
        p->per = NULL;
        p->next = NULL;
        free(p);
    }

    head->nodeNumbre--;
    return head;
}
bool isEmpty(struct headNode *head)
{
    if(head == NULL)
        return true;

    return false;

}
//显示链表
void show_list(struct headNode *head)
{
    if(isEmpty(head))
        return;

    for(struct node *p = head->first; p != NULL; p = p->next)
    {
        printf("%d\t", p->data);
    }
    printf("\n");
    printf("链表有%d个节点\n", head->nodeNumbre);
}

int main(int argc, char const *argv[])
{
    //创建链表
    struct headNode *head = creat_list();
    if(head == NULL)
        return -1;

    //修改节点
    //head = updata_Node(head,3,5);

    //删除节点
    head = removeNode(head,3);
    //增加节点
    //head = addNode(head,3,4);
    //显示链表
    show_list(head);
    return 0;
}
双向循环链表
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

typedef int dataType;

//节点
struct node
{
    dataType data;
    struct node *per;//指向上一个节点
    struct node *next;//指向下一个节点
};

//创建头节点,管理结构体
struct headNode
{
    struct node *first;//指向头节点
    struct node *tail;//指向尾节点
    dataType nodeNumbre;//记录节点数
};

//初始化管理结构体
struct headNode *init_headNode()
{
    struct headNode *head = malloc(sizeof(struct headNode));
    if(head == NULL)
        return NULL;
   
    head->first = NULL;
    head->tail = NULL;
    head->nodeNumbre = 0;

    return head;
}
//创建新节点
struct node *creat_newNode(dataType data)
{
    struct node *pnew = malloc(sizeof(struct node));
    if(pnew == NULL)
        return NULL;
   
    pnew->next = NULL;
    pnew->per = NULL;
    pnew->data = data;

    return pnew;
}

//尾插法
struct headNode *addTail()
{

}
//创建链表
struct headNode *creat_list(void)
{
    //初始化管理结构体
    struct headNode *head = init_headNode();
    if(head ==  NULL)
        return NULL;

    while(1)
    {
        dataType data;
        if(scanf("%d", &data) == 0)
        {
            while(getchar() != '\n');
            break;
        }
        //创建新节点
        struct node *pnew = creat_newNode(data);
        if(head->first == NULL)//从无到有
        {
            head->first = pnew;
            head->tail = pnew;
        }
        else//从少到多
        {
            //头插法
            //pnew->next = head->first;
            //pnew->per = head->first->per;
            //head->first->per = pnew;
            //head->first = pnew;
            //尾插法
            pnew->per = head->tail;
            head->tail->next = pnew;
            head->tail = pnew;
        }
        head->nodeNumbre++;
    }
    //循环链表
    if(head->nodeNumbre != 0)
    {
        head->tail->next = head->first;
        head->first->per = head->tail;
    }

    return head;
}

//修改节点
struct headNode *updata_Node(struct headNode *head, dataType data, dataType newData)
{
    struct node *p = head->first;
    int n = head->nodeNumbre;
    while(n)
    {
        if(p->data == data)
        {
            p->data = newData;
            break;
        }
        else
        {
           p = p->next;
        }
        n--;
    }
    if(n == 0)
    {
        printf("没有找到\n");
    }
    return head;
}
//增加节点
struct headNode *addNode(struct headNode *head, dataType data, dataType newData)
{
    struct node *pnew = creat_newNode(newData);
    struct node *p = head->first;
    if(pnew == NULL)
        return NULL;
    int n = head->nodeNumbre;
    while(n)
    {
        if(p->data == data)
        {
            break;
        }
        else
        {
            p = p->next;
        }
        n--;
    }
        if(n == (head->nodeNumbre))//首节点
        {
            printf("_%d_\n", __LINE__);
            pnew->next = head->first;
            pnew->per = head->first->per;
            head->first->per = pnew;
            head->first = pnew;
        }

        else if(n == 0)//尾节点
        {
            printf("_%d_\n", __LINE__);
            pnew->per = head->tail;
            head->tail->next = pnew;
            head->tail = pnew;
        }
        else//中间插
        {
            printf("_%d_\n", __LINE__);
            pnew->next = p;
            pnew->per = p->per;
            p->per->next = pnew;
            p->per = pnew;
        }
   
    head->nodeNumbre++;

    //循环
    if(head->nodeNumbre != 0)
    {
        head->tail->next = head->first;
        head->first->per = head->tail;
    }
    return head;
}

//删除节点
struct headNode *removeNode(struct headNode *head, dataType data)
{
    struct node *p = head->first;
    int n = head->nodeNumbre;
    while(n)
    {
        if(p->data == data)
        {
            break;
        }
        else
        {
            p = p->next;
        }
        n--;
    }
    if(n == 0)//找不到
    {
        printf("没有要删除的节点\n");
        return head;
    }
    if(n == (head->nodeNumbre))//首节点
    {
        printf("_%d_\n", __LINE__);
        head->first = p->next;
        p->next->per = head->tail;
        p->next = NULL;
        p->per = NULL;
        free(p);
    }

    else if(n == 1)//尾节点
    {
        head->tail = p->per;
        p->per->next = NULL;
        p->next = NULL;
        free(p);
    }
    else //中间节点
    {
        p->next->per = p->per;
        p->per->next = p->next;
        p->per = NULL;
        p->next = NULL;
        free(p);
    }
    head->nodeNumbre--;

     //循环
    if(head->nodeNumbre != 0)
    {
        head->tail->next = head->first;
        head->first->per = head->tail;
    }

    return head;
}

//判断链表是否有环
bool circulate(struct headNode *head)
{  
    if(head->first == NULL)
    {
        return false;
    }
    struct node *p = head->first;//快指针
    struct node *ptr = head->first;//慢指针
    do
    {
        p = p->next;
        if(p != NULL)
        {
            p = p->next;
        }
        else
        {
            return false;
        }
        ptr = ptr->next;
    }while(p != NULL && ptr != NULL && p != ptr);
    //最终地址是否相等  
    return p == ptr;

    while(p != NULL && ptr != NULL)
    {
       
    }
}

bool isEmpty(struct headNode *head)
{
    if(head->nodeNumbre == 0)
        return true;

    return false;

}

//销毁链表
void destroy_list(struct headNode *head)
{
    if(isEmpty(head))
    {
        return ;
    }

    struct node *tmp = NULL;
    struct node *p = head->first;

    int n = head->nodeNumbre;
    while(n--)
    {
        tmp = p->next;
        p->next = NULL;
        free(p);
        p = tmp;
        head->nodeNumbre--;
    }
}

//显示链表
void show_list(struct headNode *head)
{
    if(isEmpty(head))
    {
        printf("链表已销毁\n");
        return;
    }

    struct node *p = head->first;
    int n = head->nodeNumbre;
    while(n--)
    {
        printf("%d\t", p->data);
        p = p->next;
    }
    printf("\n");
    //printf("链表有%d个节点\n", head->nodeNumbre);
}



int main(int argc, char const *argv[])
{
    //创建链表
    struct headNode *head = creat_list();
    if(head == NULL)
    {
        printf("create list failed:");
        return -1;
    }

    //修改节点
    //head = updata_Node(head,3,5);

    //删除节点
    //head = removeNode(head,3);

    //增加节点
    //head = addNode(head,3,4);

    //判断链表是否有环
    if(circulate(head))
    {
        printf("该链表有环\n");
    }
    else
    {
        printf("该链表没有环\n");
    }

    //显示链表
    show_list(head);

    //销毁链表
    //destroy_list(head);
    //show_list(head);

    return 0;
}

表这个思想要好好利用

是一种逻辑结构,也是以一个特殊的线性表,特使在只能固定在一端操作,只要满足上述条件,那么这种特殊的线性表就会呈现出一种"后进先出"的逻辑,这种逻辑就被称为栈

  1. 栈顶 : 可以进行插入删除的一端。

  2. 栈底:栈顶的对端。

  3. 入栈: 将节点插入栈顶之上,也称为压栈,函数名通常为push()。

  4. 出栈:将节点从栈顶剔除,也称为弹栈,函数名通常额外pop()。

  5. 取栈顶: 取得栈顶元素,但不出栈,函数名通常为top()。

  6. 基于这种固定一端操作的简单约定,栈获得了"后进先出"的基本特征。

顺序栈;

  顺序存储意味着开辟一块连续的内存用于存储数据节点,一般而言,管理栈数据除了需要一块连续的内存之外,还需要记录栈的总容量、当前栈的元素个数、当前栈顶元素位置,如果有多线程还需要配合互斥锁和信号量等信息,为了方便管理,通常将这些信息统一于一个管理结构体中;

 

 基本操作:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef int dataType;

//定义顺序栈管理结构体
typedef struct
{
    dataType *data;//指向顺序栈首地址
    int size;//顺序栈容量
    int top;//栈顶
}seqStack;

//初始化顺序栈
seqStack *init_stack(int size)
{
    seqStack *s = malloc(sizeof(seqStack));
    if(s == NULL)
        return NULL;
   
    s->data = calloc(size, sizeof(dataType));
    if(s->data == NULL)
        return NULL;
   
    s->size = size;
    s->top = -1;

    return s;
}

//判断栈满
bool is_full(seqStack *s)
{
    return s->top == s->size - 1;
}

//判断栈为空
bool isEmpty(seqStack *s)
{
    return s->top == -1;
}

//入栈
bool push(seqStack *s, dataType data)
{
    //判断栈是否找满
    if(is_full(s))
        return false;
   
    s->data[++s->top] = data;

    return true;
}

//取栈顶,不出栈
bool top(seqStack *s, dataType *data)
{
    if(isEmpty(s))
        return false;
   
    //取栈顶元素
    *data = s->data[s->top];

    return true;
}

//出栈
bool pop(seqStack *s, dataType *data)
{
    if(!top(s,data))
    {
        return false;
    }
    s->top--;

    return true;
}

int main(int argc, char const *argv[])
{
    seqStack *s = init_stack(10);
    if(s == NULL)
    {
        printf("init stack failed\n");
        return -1;
    }

    //入栈
    while(1)
    {
        dataType data;
        if(scanf("%d", &data) == 0)//退出
            break;
        push(s,data);
    }

    //弹栈
    for(int i = s->top; i >= 0; i--)
    {
        dataType data;
        pop(s,&data);
        printf("%d\t", data);
    }
    printf("\n");

    // while (s->top != -1)
    // {
    //     dataType data;
    //     pop(s,&data);
    //     printf("%d\t",data);
    // }
    // printf("\n");
    return 0;
}
链式栈

 基本操作

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef int datatype;

// 数据节点
typedef struct node
{
    datatype data;
    struct node *next;//指向下一个节点
}node;

// 链式栈管理结构体
typedef struct linkStack
{
    node *top; // 链式栈栈顶指针
    int  size; // 链式栈当前元素个数
}linkStack;

// 初始化链式栈
linkStack * initStack(void)
{
    linkStack *s = (linkStack *)malloc(sizeof(linkStack));
    if(s == NULL)
    {
        return NULL;
    }

    s->top  = NULL;
    s->size = 0;
    return s;
}

// 判断栈是否为空
bool isEmpty(linkStack *s)
{
    return (s->size == 0);
}

//创建新节点
node *creat_node(datatype data)
{
    node *pnew = malloc(sizeof(node));
    if(pnew == NULL)
        return NULL;
    pnew->data = data;
    pnew->next = NULL;

    return pnew;
}

// 入栈
bool push(linkStack *s, datatype data)
{
    // 创建链表节点
    node *new = creat_node(data);
    if(new == NULL)
        return false;


    // 将节点置入栈顶,头插
    new->next = s->top;
    s->top = new;

    // 更新栈元素个数
    s->size++;
    return true;
}

// 取栈顶元素
node *top(linkStack *s)
{
    if(isEmpty(s))
        return NULL;

    return s->top;
}

// 出栈
node *pop(linkStack *s)
{
    node *p = top(s);
    if(p == NULL)
        return NULL;

    // 将原栈顶元素剔除出栈
    s->top = p->next;
    p->next = NULL;
    s->size--;

    return p;
}



int main(int argc, char const *argv[])
{
    //初始化链式栈
    linkStack *s = initStack();
    if(s == NULL)
        return -1;

    //入栈
    datatype n;
    scanf("%d", &n);
    while(n)
    {
        push(s,n % 8);
        n = n / 8;
    }

    // push(s,3);
    // push(s,7);
    // push(s,1);

    //出栈
    // while(s->size != 0)
    // {
    //     node *p = pop(s);
    //     if(p == NULL)
    //         return -1;
       
    //     printf("%d\t", p->data);
    // }
    while(1)
    {
        if(isEmpty(s))
        {
            break;
        }
        node *p = pop(s);
        if(p == NULL)
            return -1;
       
        printf("%d\t", p->data);

    }
    printf("\n");
    return 0;
}
 
队列
概念:
  • 只能在固定的两端操作线性表

只要满足上述条件,那么这种特殊的线性表就会呈现一种“先进先出”的逻辑,这种逻辑就被称为队列。

  • 队头:可以删除节点的一端

  • 队尾:可以插入节点的一端

  • 入队:将节点插入到队尾之后,函数名通常为enQueue()

  • 出队:将队头节点从队列中剔除,函数名通常为outQueue()

  • 取队头:取得队头元素,但不出队,函数名通常为front()

由于这种固定两端操作的简单约定,队列获得了“先进先出”的基本特性.

顺序存储的队列循环队列:

顺序存储的队列之所以被称为循环队列,是因为可以利用更新队头队尾的下标信息,来循环地利用整个数组,出队入队时也不必移动当中的数据。

需要牺牲至少数组中的一个存储位置,来区分循环队列中的满队和空队。满队和空队的约定如下:

  • 当front与rear相等时,队列为空

  • 当rear循环加一与front相等时,队列为满

与其他数据结构一样,管理循环队列除了需要一块连续的内存之外,还需要记录队列的总容量、当前队列的元素个数、当前队头、队尾元素位置,如果有多线程还需要配互斥锁和信号量等信息,为了便于管理,通常将这些信息统一于在一个管理结构体之中。

基本操作:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>    

typedef int dataType;

typedef struct
{
    dataType *data;//循环队列入口
    int cap;//队列总容量
    int front;//队头元素下标
    int rear;//队尾元素下标
}seqQueue;

//初始化队列
seqQueue *init_seqQueue(int size)
{
    seqQueue *sq = malloc(sizeof(seqQueue));
    if(sq == NULL)
        return NULL;
    sq->data = calloc(size, sizeof(dataType));
    if(sq->data == NULL)
        return NULL;
   
    sq->cap = size;
    sq->front = sq->rear = 0;
}

//判断队列是否满
bool is_full(seqQueue *sq)
{
    return (sq->rear + 1) % sq->cap == sq->front;
}

//判断队列为空
bool is_empty(seqQueue *sq)
{
    return sq->front == sq->rear;
}

//入队
bool enQueue(seqQueue *sq, dataType data)
{
    //队列是否为满
    if(is_full(sq))
    {
        return false;
    }
    //入队,尾进
    sq->data[sq->rear] = data;
    sq->rear = (sq->rear + 1) % sq->cap;

    return true;
}

//出队
bool outQueue(seqQueue*sq, dataType *data)
{
    if(is_empty(sq))
    {
        return false;
    }

    *data = sq->data[sq->front];
    sq->front = (sq->front + 1) % sq->cap;

    return true;
}
//显示
void show(seqQueue *sq)
{
    for(int i = sq->front; i != sq->rear; i = ((i + 1) % sq->cap))
    {
        printf("%d\t",sq->data[i]);
    }
    printf("\n");

}
int main(int argc, char const *argv[])
{
    //初始化队列
    seqQueue *sq = init_seqQueue(5);
    if(sq == NULL)
        return -1;
   
    while(1)
    {
        dataType data;
        if(scanf("%d", &data) == 1)
        {
            if(enQueue(sq,data) == false)
            {
                printf("队满,无法入队\n");
                continue;
            }
        }
        else
        {
            //清空缓冲区
            while(getchar() != '\n');
            if(!outQueue(sq,&data))
            {
                printf("队列为空\n");
                break;
            }
        }
        show(sq);
    }
    return 0;
}


链式队列

 基本操作:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int dataType;

//数据节点
typedef struct node
{
    dataType data;
    struct node *next;
}node;

//管理结构体
typedef struct linkQueue
{
    struct node *fron;//头节点
    struct node *rear;//尾节点
    int size;//节点数
}linkQueue;

//舒适化管理结构体
linkQueue *init_linkQueue()
{
    linkQueue *lq = malloc(sizeof(linkQueue));
    if(lq == NULL)
        return NULL;
   
    lq->fron = NULL;
    lq->rear = NULL;
    lq->size = 0;

    return lq;
}

//创建新节点
node *creat_node(dataType data)
{
    node *pnew = malloc(sizeof(dataType));
    if(pnew == NULL)
        return NULL;
   
    pnew->data = data;
    pnew->next = NULL;

    return pnew;
}

//队列为空
bool is_empty(linkQueue *lq)
{
    return lq->size == 0;
}

//入队
bool enQueue(linkQueue *lq, dataType data)
{
    //创建新节点
    node *pnew = creat_node(data);
    if(pnew == NULL)
        return false;
   
    //从无到有
    if(is_empty(lq))
    {
        lq->fron = lq->rear = pnew;
    }
    else
    {
        lq->rear->next = pnew;
        lq->rear = pnew;
    }
    lq->size++;

    return true;
}

//取队头元素,不出队
bool front(linkQueue *lq, dataType *data)
{
    if(is_empty(lq))
        return false;
   
    *data = lq->rear->data;
    return true;
}

//出队
bool outQueue(linkQueue *lq, dataType *data)
{
    if(!front(lq,data))
        return false;
   
    //将头节点剔除
    //如果链表只有一个节点
    if(lq->size == 1)
    {
        free(lq->fron);
        lq->fron = NULL;
        lq->rear = NULL;
    }
    else
    {
        node *tmp = lq->fron;
        lq->fron = tmp->next;
        tmp->next = NULL;
        free(tmp);
    }
    lq->size--;

    return true;
}

//显示
void show(linkQueue *lq)
{
    printf("队列里有元素:\t");
    for(node *p = lq->fron; p != NULL; p = p->next)
    {
        printf("%d\t",p->data);
    }
    printf("\n");

}

int main(int argc, char const *argv[])
{
    //初始化管理结构体
    struct linkQueue *lq = init_linkQueue(5);
    if(lq == NULL)
    {
        return -1;
    }

     while(1)
    {
        dataType data;
        printf("请输入:");
        if(scanf("%d", &data) == 1)
        {
            if(enQueue(lq,data) == false)
            {
                continue;
            }
        }
        else
        {
            //清空缓冲区
            while(getchar() != '\n');
            if(!outQueue(lq,&data))
            {
                printf("队列为空\n");
                break;
            }
        }
        show(lq);
    }
    return 0;
}

这些就是我这周的学习总结,这些结构需要的逻辑思维很强,学的很费力,每天都需要复习到很晚,不过现在感觉好多了。

 

 

posted @ 2023-08-05 11:11  Williekai  阅读(9)  评论(0)    收藏  举报