Data structure Week1.Day3

复习:

​ 1、什么是数据结构?

​ 专门研究数据关系和操作的学科,而非计算方法 数据结构+算法 = 程序

​ 2、逻辑结构和物理结构

  • ​ 逻辑结构:

​ 集合:除了同处于一个集合外数据元素之间没有任何关系

​ 表:数据之间存在一对一的关系

​ 树:数据之间存在一对多的关系

​ 图:数据之间存在多对多的关系

  • ​ 物理结构:(存储结构)

​ 顺序结构:数据直接存储在连续不间断的内存中,使用数据的相对位置来表示数据之间的关系

​ 链式结构:数据时分散存储在内存的任何位置,数据项中有一块指针域来表示数据之间的关系

  • ​ 物理结构和逻辑结构的对应关系:

​ 表:顺序结构、链式结构 都行

​ 树:优先采用链式结构

​ 图:顺序+链式 才好用

​ 3、数据结构的运算

​ 创建、销毁、清空、添加、删除、查询、修改、排序、遍历、访问、元素个数

​ 4、表结构

​ 顺序表:类似数组

​ 链式表:链表

​ 常考的面试题:链表和数组的优缺点?(自己总结!)

​ 5、功能受限的表

​ 栈:FILO 有且只有一个端口出

​ 问题:如果top == 栈容量是否栈满?不同的栈结构设计导致这个问题无法断定

​ top初值:0 入栈 top++ 空增栈

​ top初值:-1 top++ 入栈 满增栈

​ top初值:cal-1 出栈 top-- 满减栈

​ top初值:cal top-- 出栈 空减栈

​ 队列:FIFO 一个进一个出

​ 练习:使用两个栈结构模拟队列结构

​ 从栈A到栈B必须一个不留

​ 栈B不空栈时、栈A不能找到栈B

typedef struct Queue
{
	ArrayStack* s1;
	ArrayStack* s2;
}Queue;

Queue* create_queue(size_t cal)
{
	Queue* queue = malloc(sizeof(Queue));
	queue->s1 = create_array_stack(cal);
	queue->s2 = create_array_stack(cal);
	return queue;
}

bool full_queue(Queue* queue)
{
	return 	full_array_stack(queue->s1) && full_array_stack(queue->s2);
}

bool empty_queue(Queue* queue)
{
	return empty_array_stack(queue->s1) && empty_array_stack(queue->s1);
}

bool push_queue(Queue* queue,TYPE val)
{
	if(full_array_stack(queue->s1))
	{
		if(!empty_array_stack(queue->s2))
		{
			return false;
		}
		while(!empty_array_stack(queue->s1))
		{
			TYPE top = 0;
			top_array_stack(queue->s1,&top);
			pop_array_stack(queue->s1);
			push_array_stack(queue->s2,top);
		}
	}
	printf("push:%d\n",val);
	return push_array_stack(queue->s1,val);
}

bool pop_queue(Queue* queue)
{
	if(empty_array_stack(queue->s2))
	{
		if(empty_array_stack(queue->s1)) return false;
		while(!empty_array_stack(queue->s1))
		{
			TYPE top = 0;
			top_array_stack(queue->s1,&top);
			pop_array_stack(queue->s1);
			push_array_stack(queue->s2,top);
			
		}
	}
	int top = -1;
	top_array_stack(queue->s2,&top);
	printf("pop:%d\n",top);
	return pop_array_stack(queue->s2);
}

void destroy_queue(Queue* queue)
{
	destroy_array_stack(queue->s1);
	destroy_array_stack(queue->s1);
}

封装:尾添加的效率低,非法下标的判断效率也很低。

​ 1、单链表

  • ​ 节点:数据域 指针域
  • ​ 数据项:头指针 尾指针 节点数量
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

#define TYPE int 

typedef struct Node
{
	TYPE data;
	struct Node* next;
}Node;

typedef struct List
{
	Node* head;
	Node* tail;
	size_t size;
}List;

Node* create_node(TYPE data)
{
	Node* node = malloc(sizeof(Node));
	node->data = data;
	node->next = NULL;
	return node;
}

List* create_list(void)
{
	List* list = malloc(sizeof(List));
	list->head = create_node(0); //only for tool
	list->tail = NULL;
	list->size = 0;
	return list;
}

void add_head_list(List* list,TYPE data)
{
	Node* node = create_node(data);
	if(0 == list->size)
	{
		list->head->next = node;
		list->tail = node;
	}
	else
	{
		node->next = list->head->next;
		list->head->next = node;
	}
	list->size++;
}

void add_tail_list(List* list,TYPE data)
{
	Node* node = create_node(data);
	if(0 == list->size)
	{
		list->head->next = node;
		list->tail = node;
	}
	else
	{
		list->tail->next = node;
		list->tail = node;
	}
	list->size++;
}

bool del_head_list(List* list)
{
	if(0 == list->size) return false;
	Node* temp = list->head->next;
	list->head->next = temp->next;
	if(1 == list->size) list->tail = NULL;
	free(temp);
	list->size--;
	return true;
}

bool del_tail_list(List* list)
{
	if(0 == list->size) return false;
	free(list->tail);
	if(1 == list->size)
	{
		list->head->next =NULL;
		list->tail = NULL;
	}
	else
	{
		Node* n = list->head->next;
		while(n->next!=list->tail) n = n->next;
		n->next = NULL;
		list->tail = n;
	}
	list->size--;
	return true;
}

bool insert_list(List* list,int index,TYPE data)
{
	if(index < 0 || index >= list->size) return false;
	Node* node = create_node(data);
	Node* prev = list->head;
	for(int i=0;i<index;i++)
	{
		prev = prev->next;
	}
	node->next = prev->next;
	prev->next = node;
	list->size++;
	return true;
}

bool del_val_list(List* list,TYPE data)
{
	if(data == list->head->next->data) return del_head_list(list);
	if(data == list->tail->data) return del_tail_list(list);
	for(Node* n = list->head->next;n->next != NULL;n= n->next)
	{
		if(n->next->data == data)
		{
			Node* temp = n->next;
			n->next = temp->next;
			free(temp);
			list->size--;
			return true;
		}
	}
	return false;
}

bool del_index_list(List* list,int index)
{
	if(index < 0 || index >= list->size) return false;
	if(index == 0) return del_head_list(list);
	if(index == list->size-1) del_tail_list(list);
	Node* prev =list->head->next;
	for(int i=1;i<index;i++)
	{
		prev = prev->next;
	}
	Node* temp = prev->next;
	prev->next = temp->next;
	free(temp);
	list->size--;
	return true;
}

bool modify_index_list(List* list,int index,TYPE data)
{
	if(index < 0 || index >= list->size) return false;
	Node* n = list->head->next;
	for(int i=1;i<index;i++)
	{
		n = n->next;
	}
	n->data = data;
	return true;
}

bool modify_val_list(List* list,TYPE old,TYPE data)
{
	bool flag = false;
	for(Node* n = list->head->next; n ; n = n->next)
	{
		if(n->data == old)
		{
			n->data = data;
			flag = true;
		}
	}
	return flag;
}

size_t query_list(List* list,TYPE data)
{
	int cnt = 0;
	for(Node* n = list->head->next;n->next != NULL;n= n->next)
	{
		if(data == n->data) return cnt;
		cnt++;
	}
	return -1;
}

void sort_list(List* list)
{
	for(Node* n = list->head->next;n->next != NULL;n=n->next)
	{
		for(Node* j=n->next;j;j=j->next)
		{
			if(n->data > j->data)
			{
				int temp = j->data;
				j->data = n->data;
				n->data = temp;
			}
		}
	}
}

bool access_list(List* list,int index,TYPE* val)
{
	if(index < 0 || index >= list->size) return false;
	Node* n = list->head->next;
	for(int i=0;i<index;i++)
	{
		n = n->next;
	}
	*val = n->data;
	return true;
}

void clean_list(List* list)
{
	while(list->tail) del_tail_list(list);
}

void destroy_list(List* list)
{
	clean_list(list);
	free(list->head);
	free(list);
}

void show_list(List* list)
{
	for(Node* n=list->head->next;n;n=n->next)
	{
		printf("%d ",n->data);
	}
	printf("\n");
}
int main(int argc,const char* argv[])
{
	List* list = create_list();
	for(int i=0;i<10;i++)
	{
		add_tail_list(list,i);
	}
	printf("original\n");
	show_list(list);
	
	for(int i=0;i<5;i++)
	{
		del_head_list(list);
	}
	printf("afte deling\n");
	show_list(list);
	
	insert_list(list,0,1000);
	printf("after inserting\n");
	show_list(list);
	
	del_val_list(list,1000);
	printf("after deling 1000\n");
	show_list(list);

	del_index_list(list,0);
	printf("after deling index:0\n");
	show_list(list);

	modify_index_list(list,0,888);
	printf("modify index:0 value to 888\n");
	show_list(list);

	modify_val_list(list,888,8888);
	printf("modify 888 to 8888\n");
	show_list(list);

	printf("find index of 7\n");
	printf("8888:index%d",query_list(list,7));
	
	sort_list(list);
	printf("after sort list\n");
	show_list(list);

	int num = 0;
	access_list(list,0,&num);
	printf("access index:0 of list is %d\n",num);
}

​ 2、静态链表

​ 节点:数据域 游标

​ 静态链表的节点存储在连续的内存中,通过游标来访问下一个节点

​ 原因:其他的高级语言没有指针

​ 这种链表在插入删除时只能通过修改游标的值,而不用申请和释放内存来达到链式结构的目的

​ 但是也是牺牲了随机访问的功能,是一种给没有指针的编译实现单链表

​ 3、循环链表

​ 链表的最后一个节点的next不再指向NULL,而是指向头节点,这种链表叫做单向循环链表

​ 它的优点:可以在任何一个节点可以访问到链表中的任意节点,它的好处可以通过任意节点遍历整个链表

​ 4、双向链表

​ 双向循环链表

​ 节点:前趋指针 数据域 后继指针

​ 5、Linux的内核链表

​ 6、通用链表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值