线性存储&链式存储(5.14)

本文详细介绍了数据结构中的两种基本存储方式——顺序存储和链式存储。顺序存储通过数组实现,适合线性关系的数据,操作包括增删改查排序。链式存储则利用节点记录下一个节点地址,支持更灵活的操作,如创建、插入和输出链表数据。文中还提出了链表有序插入和逆置的作业挑战。

顺序存储:

一  数据结构

 

(1)数据存储  (顺序存储,链式存储,索引存储,哈希存储)

(2)数据间关系(逻辑关系:线性,非线性)

(3)数据操作  (增 删 改 查 排序)

 

 

二 线性关系-----顺序表 = 存放数据的空间[数组]  + 当前数据的个数

 

1.数据结构 

typedef int DATATYPE;

typedef struct 
{
	DATATYPE buf[MAX];//存放数据 
	int n;//记录当前数据的个数
}SeqList;

2.操作 

SeqList *create_seqlist()
{
	SeqList *L;

	//分配内存
	L = (SeqList *)malloc(sizeof(SeqList));
	L->n = 0;

	return L;
}

int insert_seqlist(SeqList *L,DATATYPE data)
{
	//判断顺序表是否满
	//如果满,则输出"The SeqList is full!",然会返回-1

	
	//插入数据
	L->buf[L->n] = data;

	L->n ++;

	return 0;
}

int printf_seqlist(SeqList *L)
{
	...
}

int sort_seqlist(SeqList *L)
{
	for(i = 0;i < L->n - 1;i ++)
	{
		for(j = 0;j < L->n - i - 1;j ++)
		{
			...
		}
	}

}

int find_seqlist(SeqList *L,DATATYPE data)
{
	for(i = 0;i < L->n;i ++)
	{
		if(L->buf[i] == data)
			break;
	}

	return (i + 1);
}

int insert_post_seqlist(SeqList *L,int post,DATATYPE data)
{
	1.判断是否满 和 合法位置 [1,L->n],如果是非法位置,需要输出位置非法
	2.指定位置插入的思想
	  [1]最后一个元素的下标 L->n - 1
	  [2]从后向前移动
	  for(i = L->n - 1;? ;i --)
	  {
		  L->buf[i + 1] = L->buf[i];
	  }
	 [3]插入 
	 L->buf[?] = data;
	 [4]更新n的值
	
	return 0;
}

int delete_data_seqlist(SeqList *L,DATATYPE data)
{
	...
	//提示:删除字符的选择题思路
}

int main()
{
	SeqList *L;

	L = create_seqlist();
	//插入10个数据到顺序表

	//输出顺序表
}

代码如下:

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

#define MAX 10

typedef int DATATYPE;

typedef struct 
{
	DATATYPE data[MAX];
	int n;
}SeqList;

SeqList *create_seqlist()
{
	SeqList *L;

	L = (SeqList *)malloc(sizeof(SeqList));
	if(L == NULL){
		printf("NO free memory!\n");
		return NULL;
	}

	L->n = 0;

	return L;
}

int insert_seqlist(SeqList *L,DATATYPE data)
{
	if(L->n == MAX)
	{
		printf("The SeqList is full!\n");
		return -1;
	}

	L->data[L->n] = data;
	L->n ++;

	return 0;
}

int printf_seqlist(SeqList *L)
{
	int i = 0;

	for(i = 0;i < L->n ;i ++)
	{
		printf("%d ",L->data[i]);
	}
	printf("\n");

	return 0;
}

int insert_postion_seqlist(SeqList *L,int post,DATATYPE data)
{
	int last;

	//判断位置合法性[1,L->n]
	if(!(post >= 1 && post <= L->n))
	{
		printf("The invaild postion : %d,must [1,%d]\n",post,L->n);
		return -1;
	}

	//判断是否满
	if(L->n == MAX)
	{
		printf("The SeqList is full\n");
		return -1;
	}
	
	//从后向前移动数据
	for(last = L->n - 1;last >= post - 1;last --)
	{
		L->data[last + 1] = L->data[last];
	}

	//插入数据
	L->data[post - 1] = data;
	
	//更新n的值
	L->n ++;

	return 0;
}

int delete_assign_data(SeqList *L,DATATYPE data)
{
	int i,j;

	//判断是否空 
	if(L->n == 0)
	{
		printf("The SeqList is empty!\n");
		return -1;
	}

	//删除数据代碼
	for(i = 0,j = 0;i < L->n;i ++)
	{
		if(L->data[i] != data)
		{
			L->data[j++] = L->data[i];
			//j ++;
		}
	}
	
	//判断要删除的元素是否存在
	if(i == j){
		printf("The delete data:%d is not exist!\n",data);
		return -1;
	}

	//更新剩余数据的个数
	L->n = j;

	return 0;
}

int sort_seqlist(SeqList *L)
{
	int i,j;
	DATATYPE temp;

	for(i = 0;i < L->n - 1;i ++)//需要排的次数
	{
		for(j = 0;j < L->n - 1  - i;j ++)//比较方法:前一个元素与后一个元素比较,每排序一次则少一个元素
		{
			if(L->data[j] > L->data[j+1])
			{
				temp = L->data[j];
				L->data[j] = L->data[j+1];
				L->data[j+1] = temp;
			}
		}
	}

	return 0;
}

int delete_repeat_data(SeqList *L)
{
	int k;
	int i,j;

	for(i = 0;i < L->n ;i ++)
	{
		for(j = i + 1,k = i + 1;j < L->n;j ++)
		{
			if(L->data[j] != L->data[i])
			{
				L->data[k] = L->data[j];
				k ++;
			}
		}

		L->n = k;
	}


	return 0;
}

int main(int argc, const char *argv[])
{
	int i = 0;
	int a[] = {10,20,10,40,40,90,40,80,20};
	SeqList *L;
	
	L = create_seqlist();
	if(L == NULL)
		return -1;
	
	for(i = 0;i < sizeof(a)/sizeof(a[0]);i ++)
	{
		insert_seqlist(L,a[i]);
	}
	
	printf_seqlist(L);

	insert_postion_seqlist(L,3,100);
	insert_postion_seqlist(L,5,100);
	printf_seqlist(L);
	
	delete_assign_data(L,100);
	
	printf_seqlist(L);

	delete_assign_data(L,101);
	
	sort_seqlist(L);

	printf_seqlist(L);
	
	delete_repeat_data(L);

	printf_seqlist(L);

	return 0;
}


链式存储:

一 链式存储

 

[1]头节点记录第一个有效数据节点的首地址,本身不存放数据 

[1]每个节点会记录下一个节点的地址

[2]尾节点是最后一个节点,它记录的地址为0(NULL)

 

1.节点的类型设计

typedef struct node
{
	DATATYPE data;//存放数据
	struct node *next;//记录下一个节点的地址
}LinkNode;

2.操作

[1]创建空链表

LinkNode *create_empty_linklist()
{
	LinkNode *head;

	head = (LinkNode *)malloc(sizeof(LinkNode));
	head->next = NULL;

	return head;
}

[2]插入新节点

   <1>头插法(每次都是在头节点后面插入数据)

int insert_head_linklist(LinkNode *head,DATATYPE data)
{
		分配一个节点
		将data存放在新节点

		新节点保存头的后一个节点地址
		头节点保存新节点地址
}

   <2>尾插法(每次都是在尾部节点后面插入数据)

int insert_tail_linklist(LinkNode *head,DATATYPE data)

[3]输出链表中的数据

int printf_linklist(LinkNode *head)

作业:

(1)实现一个链表的有序插入

int a[] = {10,3,4,15,6};
LinkNode *L = create_empty_linklist();

for(i  = 0;i < sizeof(a)/sizeof(a[0]);i ++)
{
	insert_order_linklist(L,a[i]);
}

printf_linklist(L);//3,4,6,10,15

(2)实现一个链表的逆置


代码如下:

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

typedef int DATATYPE;

typedef struct node
{
	DATATYPE data;
	struct node *next;
}LinkNode;

LinkNode *create_linklist()
{
	LinkNode *head;

	head = (LinkNode *)malloc(sizeof(LinkNode));
	if(head == NULL){
		printf("No free memory!\n");
		return NULL;
	}
	head->next = NULL;
	
	return head;
}

int insert_head_linklist(LinkNode *head,DATATYPE data)
{
	LinkNode *temp;

	temp = (LinkNode *)malloc(sizeof(LinkNode));
	temp->data = data;

	//用新节点记录头的后一个节点
	temp->next = head->next;
	//用头节点记录新节点
	head->next = temp;
	
	return 0;
}

int insert_tail_linklist(LinkNode *head,DATATYPE data)
{
	LinkNode *temp;
	LinkNode *p = head;

	//找到尾部节点
	while(p->next != NULL)
	{
		p = p->next;
	}

	temp = (LinkNode *)malloc(sizeof(LinkNode));
	temp->data = data;
	temp->next = NULL;

	//在尾部链接新节点
	p->next = temp;

	return 0;
}

int printf_linklist(LinkNode *head)
{
	LinkNode *p;
	
	for(p = head->next;p != NULL;p = p->next)
	{
		printf("%d ",p->data);
	}
	printf("\n");

	return 0;
}

int delete_assign_linklist(LinkNode *head,DATATYPE data)
{
	LinkNode *q = head;
	LinkNode *p = head->next;
	
	while(p)
	{
		if(p->data == data)
		{
			q->next = p->next;
			free(p);
			p = q->next;//重新让p在q的前面
		
		}else{//不是要删除的元素,则p,q一起移动
			p = p->next;
			q = q->next;
		}
	}
	
	return 0;
}

int find_mid_linklist(LinkNode *head)
{
	LinkNode *p = head->next;//走两步
	LinkNode *q = head->next;//走一步

	while(1)
	{
		//走两步 
		p = p->next;
		if(NULL == p)
			break;

		p = p->next;		
		if(p == NULL)
			break;

		//走一步 
		q = q->next;
	}

	printf("mid : %d\n",q->data);
	
	return 0;
}

int insert_order_linklist(LinkNode *head,DATATYPE data)
{
	LinkNode *temp;
	LinkNode *q = head;
	LinkNode *p = head->next;

	while(p)
	{
		if(p->data > data){
			break;
		}else{
			p = p->next;
			q = q->next;
		}
	}

	temp = (LinkNode *)malloc(sizeof(LinkNode));
	temp->data = data;

	temp->next = q->next;
	q->next    = temp;

	return 0;
}

//算法:链表的插入排序
//思想:
//    1.断开头和后面的节点
//    2.有序插入后面的数据节点
int sort_linklist(LinkNode *head)
{
	LinkNode *k;
	LinkNode *t;
	LinkNode *p,*q;

	//断开
	t = head->next;
	head->next = NULL;
	
	while(t != NULL)
	{
		q = head;
		p = head->next;

		while(p)
		{
			if(p->data > t->data)
			{
				break;
			}else{
				p = p->next;
				q = q->next;
			}
		}

		//k先保存t后面的节点
		k = t->next;
		t->next = q->next;
		q->next = t;

		//让t走到k的位置
		t = k;
	}

	return 0;
}

int clean_linklist(LinkNode *head)
{
	LinkNode *temp;

	while(head != NULL)
	{
		//保存头面的节点
		temp = head->next;
		//删除头节点
		free(head);
		//修改head为temp
		head = temp;
	}

	return 0;
}


int main(int argc, const char *argv[])
{
	int i;
	int a[] = {200,100,300};
	LinkNode *L1 = create_linklist();
	LinkNode *L2 = create_linklist();
	LinkNode *L3 = create_linklist();

	for(i = 0;i < sizeof(a)/sizeof(a[0]);i ++)
	{
		insert_head_linklist(L1,a[i]);
		insert_tail_linklist(L2,a[i]);
		insert_order_linklist(L3,a[i]);
	}
	
//	printf_linklist(L3);
	printf_linklist(L2);

	printf("sort L2:");
	sort_linklist(L2);
	printf_linklist(L2);


	printf_linklist(L1);
	
	delete_assign_linklist(L2,250);
	printf_linklist(L2);

	find_mid_linklist(L1);
	find_mid_linklist(L2);
	
	insert_order_linklist(L2,250);
	insert_order_linklist(L2,250);
	printf_linklist(L2);

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值