数据结构 day03

3. 线性表

3.2. 链表

3.2.2. 单向链表

有头单向链表的函数操作

5. 链表指定位置删除数据

int deletePostLinkList(link_node_t *p, int post)
{
    // 容错判断
    if (post < 0 || post >= lengthLinkList(p) || p->next == NULL)
    {
        perror("Delete location error");
        return -1;
    }

    // 头指针移动到post的前一个节点的地址
    for (int i = 0; i < post; i++)
        p = p->next;

    // 定义pdel ,指向被删除节点
    link_list_t pdel = p->next;

    // 头指针指针域跨过被删除节点
    p->next = pdel->next;

    // 释放被删除节点的地址,pdel置空
    free(pdel);
    pdel = NULL;
    
    return 0;
}

6. 判断链表是否为空

int isEmptyLinkList(link_node_t *p)
{
    return p->next == NULL;
}

7. 清空单向链表

// 头节点不动,每次删除头节点后面的节点,让头节点的指针域跨过被删除节点
void clearLinkList(link_node_t *p)
{
    // 定义pdel
    link_list_t pdel = NULL;
    // 循环删除
    while (p->next != NULL)
    {
        // 指向被删除节点,头节点的下一个节点
        pdel = p->next;
        // 头节点的指针域跨过被删除节点
        p->next = pdel->next;
        // 释放被删除节点
        free(pdel);
        pdel = NULL;
    }
}

8. 修改指定位置的数据

int changePostLinkList(link_node_t *p, int post, datatype data)
{
    // 容错判断
    if (post < 0 || post >= lengthLinkList(p))
    {
        perror("post err!!");
    }
    else if (isEmptyLinkList(p))
    {
        printf("The linked list is empty!!\n");
    }

    // 头指针指向被修改的节点
    for (int i = 0; i <= post; i++)
    {
        p = p->next;
    }

    // 修改数据
    p->data = data;

    return 0;
}

9. 查找指定数据出现的位置

int searchDataLinkList(link_node_t *p, datatype data)
{
    // 定义一个变量,存放查找到的下标
    int post = 0;

    // 遍历链表
    while (p != NULL)
    {
        p = p->next;
        // 节点的数据域与data比较
        if (p->data == data)
        {
            // 相等结束返回下标
            return post;
        }
        // 不相等,变量++
        post++;
    }

    // 遍历结束没找到,返回-1
    return -1;
}

10. 删除单向链表中出现的指定数据

int deleteDataLinkList(link_node_t *p, datatype data)
{
    // 定义一个pdel, 用来指向被删除节点
    link_list_t pdel = p->next;

    //计算一共删了多少个
    int i = 0;

    // 指针q 遍历链表
    while (pdel != NULL)
    {
        if (pdel->data == data)
        {
            p->next = pdel->next; // 跨过被删除节点
            free(pdel);           // 删除节点
            pdel = p->next;
            i++;
        }
        else
        {
            p = p->next;
            pdel = pdel->next;
        }
    }

    return i;
}

11. 转置链表

void reverseLinkList(link_node_t *p)
{
    // 定义 ptail,最后指向最后一个节点
    link_list_t ptail = p->next;
    // 定义指针temp,指向尾指针的下一个节点
    link_list_t t = ptail->next;

    while (ptail->next != NULL)
    {
        t = ptail->next;
        ptail->next = t->next;
        t->next = p->next;
        p->next = t; 
    }
}

3.2.3. 单向循环链表

        约瑟夫环问题,是一个经典的循环链表问题,题意是:已知 n 个人(分别用编号 1,2,3,…,n 表示)围坐在一张圆桌周围,从编号为 k 的人开始顺时针报数,数到 m 的那个人出列;他的下一个人又从 1 开始,还是顺时针开始报数,数到 m 的那个人又出列;依次重复下去,直到圆桌上剩余一个人。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

typedef struct node_t
{
	int data;
	struct node_t *next;
}link_node_t,*link_list_t;

int main(int argc, const char *argv[])
{
	int i;
	link_list_t pdel = NULL;    //用于指向被删除节点
	link_list_t ptail = NULL;    //永远指向当前链表的尾 
	link_list_t pnew = NULL;    //永远指向新创建的节点
	link_list_t h = NULL;
	int all_num = 7;    //猴子总数 
	int start_num = 2;     //从几号猴子开始数
	int kill_num = 3;    //数到几杀死猴
	// printf("请您输入猴子总数 起始号码 数到几杀死:\n");
	// scanf("%d%d%d",&all_num,&start_num,&kill_num);

	//1.创建出一个单向循环链表
	    //(1)创建有all_num个节点的单向链表
	h = (link_list_t)malloc(sizeof(link_node_t));
	if(NULL == h)
	{
		perror("malloc failed");
		return -1;
	}
	h->data = 1;
	h->next = NULL;
	ptail = h;    //尾指针指向当前的第一个节点
	for(i = 2; i <= all_num; i++)
	{
		//创建新的节点
		pnew = (link_list_t)malloc(sizeof(link_node_t));
		if(NULL == pnew)
		{
			perror("malloc failed");
			return -1;
		}
		//将新节点装上数据
		pnew->data = i;
		pnew->next = NULL;
		//将新节点链接到链表尾 
		ptail->next = pnew;    //链接到链表的尾
		ptail = pnew;    //尾指针继续指向当前链表的尾 
	}
	//(2)将头指针保存到链表的尾形成单向循环链表
	ptail->next = h;    //形成单向循环链表 

	//2.开始杀猴子 
	//(1)将头指针移动到开始猴子的号码处 
	for(i = 1; i < start_num; i++)
		h = h->next;
        printf("start :%d\n",h->data);

	//(2)循环进行杀猴子
 	while(h != h->next)//终止:就剩一个猴子,只有一个节点
	{
		//将头指针移动到即将删除节点的前一个节点
		for(i = 1; i < kill_num-1; i++)
			h = h->next;

		pdel = h->next;
		//跨过删除节点
		h->next = pdel->next;
		printf("kill is -------------%d\n",pdel->data);
		free(pdel);
		pdel = NULL;
		//杀死猴子猴后,从下一个节点开始继续开始数,将头指针移动到开始数的地方
		h = h->next;
	}
	printf("king is=================== %d\n",h->data);
	return 0;
}	

4. 栈—stack

4.1. 什么是栈

1. 入栈和出栈只能在一端完成,另一端是封闭的

2. 遵循先入后出 FILO,后入先出 LIFO

3. 完成入栈出栈操作的一段成为栈顶,另一端称为栈底

4. 栈是只能在一端插入和删除的线性表,又称堆栈

4.2. 顺序栈

4.2.1. 特性

逻辑结构:线性结构

存储结构:顺序存储

操作:创建,入栈,出栈,清空,判空,判满

4.2.2. 代码实现

头文件:seqstack.h

#ifndef __SEQSTACK_H__
#define __SEQSTACK_H__

typedef int datatype;
typedef struct seqstack
{
    datatype *data; //指向栈的存储位置
    int maxlen;     //保存栈的最大长度
    int top;        //称为栈针,用的时候可以当作顺序表里的last来使用
                    //top始终代表当前栈内最后一个有效元素的下标
} seqstack_t;

//1.创建一个空栈,len代表创建栈时的最大长度。
seqstack_t *createEmptySeqStack(int len);
//2.判断是否为满,满返回1 未满返回0
int isFullSeqStack(seqstack_t *p);
//3.入栈,data代表入栈的数据
int pushStack(seqstack_t *p, int data);
//4.判断栈是否为空
int isEmptySeqStack(seqstack_t *p);
//5.出栈,返回出栈数据
int popSeqStack(seqstack_t *p);
//6. 清空栈
void clearSeqStack(seqstack_t *p);
//7. 获取栈顶数据(注意不是出栈操作,如果出栈,相当于删除了栈顶数据,只是将栈顶的数据获取到,不需要移动栈针)
int getTopSeqStack(seqstack_t *p);
//8. 求栈的长度,返回长度。
int lengthSeqStack(seqstack_t *p);
#endif

1. 创建一个空栈

// 1.创建一个空栈,len代表创建栈时的最大长度。
seqstack_t *createEmptySeqStack(int len)
{
    // 申请空间存放栈的结构
    seqstack_t *p = (seqstack_t *)malloc(sizeof(seqstack_t));
    if (p == NULL)
    {
        printf("Space opening failure!!\n");
        return -1;
    }

    // 初始化
    p->maxlen = len;
    p->top = -1;
    p->data = (datatype *)malloc(sizeof(datatype) * len);
    if (p->data == NULL)
    {
        printf("initialization failed!!\n");
        return -1;
    }
    return p;
}

2. 判断是否为满

int isFullSeqStack(seqstack_t *p)
{
    return p->top+1 == p->maxlen;
}

3. 入栈

int pushStack(seqstack_t *p, int data)
{
    // 容错判断
    if (isFullSeqStack(p))
    {
        printf("Space is full!!\n");
        return -1;
    }

    // 入栈操作
    p->data[++p->top] = data;

    return 0;
}

4.  判断是否为空

int isEmptySeqStack(seqstack_t *p)
{
    return p->top == -1;
}

5. 出栈

int popSeqStack(seqstack_t *p)
{
    // 容错判断
    if (isEmptySeqStack(p))
    {
        printf("Space is empty!!\n");
    }

    return p->data[p->top--];
}

6. 清空栈

void clearSeqStack(seqstack_t *p)
{
    p->top = -1;
}

7. 获取最顶上的数据,不是出栈

int getTopSeqsStack(seqstack_t *p)
{
    // 容错判断
    if (isEmpSeqStack(p))
    {
        printf("Space is empty!!\n");
    }

    return p->data[p->top];
}

8. 求栈的长度,返回长度

int lengthSeqStack(seqstack *p)
{
    reutrn p->top+1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值