数据结构笔记之线性存储

线性结构[把所有的节点用一根直线穿起来]
A:连续存储[数组]
1.什么叫数组
元素类型相同,大小相等
2.数组的优缺点


实例:数组操作

#include <stdio.h>
#include<malloc.h>
#include <stdlib.h>
struct Arr
{
	int * pBase;		//数组第一个元素的地址
	int len;			//数组长度
	int cnt;			//有效元素个数
	//int incremant;		//自动增长因子
};
void init_arr(struct Arr * pArr, int length);
bool append_arr(struct Arr * pArr, int val);			//追加
bool insert_arr(struct Arr * pArr, int pos, int val);   //pos从1开始
bool delete_arr(struct Arr * pArr, int pos, int * pval);
bool get(struct Arr * pArr, int pos, int * pval);
bool is_empty(struct Arr * pArr);
bool is_full(struct Arr * pArr);
void show_arr(struct Arr * pArr);
void inversion_arr(struct Arr * pArr);
void sort_arr(struct Arr * pArr);
//find deleteAll

int main()
{
	struct Arr arr;
	int Val;
	init_arr(&arr, 6);
	show_arr(&arr);
	append_arr(&arr, 1);
	append_arr(&arr, 2);
	append_arr(&arr, 3);
	append_arr(&arr, 4);
	show_arr(&arr);

	if(delete_arr(&arr, 1, &Val))
	{
		printf("删除成功,元素的值为%d\n", Val);
	}
	else
	{
		printf("删除失败\n");
	}
	show_arr(&arr);

	inversion_arr(&arr);
	show_arr(&arr);

	sort_arr(&arr);
	show_arr(&arr);
	get(&arr, 1, &Val);
	printf("得到的值为%d\n", Val);
	/*append_arr(&arr, 2);
	append_arr(&arr, 3);
	append_arr(&arr, 4);
	append_arr(&arr, 5);
	//append_arr(&arr, 6);
	insert_arr(&arr, 6, 99);
	show_arr(&arr);*/
	//printf("%d\n" , arr.len);
	return 0;
}

void init_arr(struct Arr * pArr, int length)
{
	pArr->pBase = (int *)malloc(sizeof(int)*length);
	if(NULL == pArr->pBase)
	{
		printf("动态内存分配失败");
		exit(-1);
	}
	else
	{
		pArr->len = length;
		pArr->cnt = 0;
	}
	return;
}

bool is_empty(struct Arr * pArr)
{
	if(0 == pArr->cnt)
		return true;
	else
		return false;
}

bool is_full(struct Arr * pArr)
{
	if(pArr->cnt == pArr->len)
	{
		return true;
	}
	else
	{
		return false;
	}
}

void show_arr(struct Arr * pArr)
{
	if(is_empty(pArr))
	{
		printf("数组为空!\n");
	}
	else
	{
		for(int i=0; i<pArr->cnt; ++i)
			printf("%d ", pArr->pBase[i]);
		printf("\n");
	}
}

bool append_arr(struct Arr * pArr, int val)
{
	if( is_full(pArr) )
	{
		return false;
	}
	else
	{
		pArr->pBase[pArr->cnt]=val;
		pArr->cnt++;
		return true;
	}
}

bool insert_arr(struct Arr * pArr, int pos, int val)  //3 88
{

	if( is_full(pArr) )
		return false;
	if(pos<1 || pos>pArr->cnt+1)
		return false;
		
	for(int i=pArr->cnt-1;i>=pos-1;i--)
	{
		pArr->pBase[i+1]=pArr->pBase[i];
	}
	pArr->pBase[pos-1] = val;
	pArr->cnt++;
	return true;
}


bool delete_arr(struct Arr * pArr, int pos, int * pval)
{
	if( is_empty(pArr) )
		return false;
	if(pos<1 || pos>pArr->cnt)
		return false;

	*pval = pArr->pBase[pos-1];
	for(int i=pos; i<pArr->cnt; i++)
	{
		pArr->pBase[i-1] = pArr->pBase[i];
	}
	pArr->cnt--;
}


void inversion_arr(struct Arr * pArr)
{
	int t;
	for(int i=0;i<=pArr->cnt/2;i++)
	{
		t = pArr->pBase[i];
		pArr->pBase[i]=pArr->pBase[pArr->cnt-1-i];
		pArr->pBase[pArr->cnt-1-i] = t;
	}

	return;
}

void sort_arr(struct Arr * pArr)
{
	int i, j, t;
	for(i=0; i<pArr->cnt; i++)
	{
		for(j=i+1; j<pArr->cnt; j++)
		{
			if(pArr->pBase[i]>pArr->pBase[j])
			{
				t = pArr->pBase[i];
				pArr->pBase[i] = pArr->pBase[j];
				pArr->pBase[j]=t;
			}
		}
	}
}


bool get(struct Arr * pArr, int pos, int * pval)
{
	*pval = pArr->pBase[pos-1];	
	return true;
}


B:离散存储[链表]
1.定义:
n个节点离散分配
彼此通过指针相连
每个节点只有一个前驱结点,每个节点只有一个后续阶段
首节点没有前驱节点,尾节点没有后续节点

专业术语:
首节点:
第一个有效的节点
尾节点:
最后一个有效的节点
头结点:
在首节点前加一个头结点,便于链表操作(不存放有效数据)
头指针
指向头结点的指针变量
尾指针
指向尾节点的指针变量
需要用函数对链表进行处理,需要接受那些参数:
只需要知道一个参数:头结点

2.分类:
单链表 
双链表(两个指针域) 
循环链表(通过任何一个节点找到其他) 
非循环链表
3.算法:
遍历
查找
清空
销毁
求长度
排序
删除节点 r = p->pNext; P->pNext = p->pNext->pNext; free(r);
插入节点 写法1.r = p->pNext; p->pNext = q; q->pNext = r;
写法2.q->pNext = p->pNext; p->pNext=q; 
算法:
狭义的算法与数据存储相关,广义的算法与存储方式无关
泛型:
利用某种技术发到的效果就是:不同的存数方式执行的操作时一样的

4.链表的优缺点:

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


typedef struct Node
{
	int data;
	struct Node * pNext;
}Node, *PNODE;

PNODE create_list(void);
void traverse_list(PNODE pHead);
bool is_empty(PNODE pHead);
int	 length_list(PNODE pHead);
bool insert_list(PNODE pHead, int pos, int val);
bool delete_list(PNODE pHead, int pos, int * pVal);	//最后一个删除值
void sort_list(PNODE pHead);


int main()
{
	int len = 0;
	int val = 0;
	PNODE pHead  = NULL;
	
	pHead = create_list();
	traverse_list(pHead);

	if(is_empty(pHead))
	{
		printf("空\n");
		return 0;
	}
	else
		printf("不空\n");

	len = length_list(pHead);
	printf("%d\n",len);

	sort_list(pHead);
	traverse_list(pHead);
	
	insert_list(pHead, 3, 4);
	traverse_list(pHead);


	if( delete_list(pHead, 3, &val) )
	{
		printf("删除成功\n");
		printf("删除值为%d\n", val);
	}
	else
	{
		printf("删除失败!\n");
	}
	traverse_list(pHead);

	return 0;
}

/*
**创建一个非循环链表
*/
PNODE create_list(void)
{
	int len;
	int i;
	int val;
	//分配了一个不存放有效数据的头结点
	PNODE pHead = (PNODE)malloc(sizeof(PNODE));
	if(NULL == pHead)
	{
		printf("分配失败,程序终止!\n");
		exit(-1);
	}
	
	PNODE pTail =pHead;		//pHead赋值给pTail,使得pTail->指向尾节点
	pTail->pNext = NULL;	//防止0个节点

	printf("请输入需要生成链表节点个数:\n");
	scanf("%d", &len);

	for(i=0;i<len;++i)
	{
		printf("请输入读%d个节点的值:",i+1);
		scanf("%d", &val);

		PNODE pNew = (PNODE)malloc(sizeof(PNODE));
		if(NULL == pHead)
		{
			printf("分配失败,程序终止!\n");
			exit(-1);
		}
		pNew->data = val;		//节点存放数据
		pTail->pNext = pNew;	//前一个节点指向当前
		pNew->pNext = NULL;		//此节点指向NULL
		pTail = pNew;
	}
	return pHead;
}

void traverse_list(PNODE pHead)
{
	PNODE p = pHead->pNext;
	
	while(NULL != p)
	{
		printf("%d ", p->data);
		p = p->pNext; 
	}
	printf("\n");
}

bool is_empty(PNODE pHead)
{
	if(NULL == pHead->pNext)
		return true;
	else
		return false;
}

int length_list(PNODE pHead)
{
	PNODE p = pHead->pNext;
	int len = 0;
	
	while(NULL != p)
	{
		++len;
		p = p->pNext;
	}

	return len;
}

void sort_list(PNODE pHead)
{
	int i, j, t;
	PNODE p, q;
	int len = length_list(pHead);
	for(i=0,p=pHead->pNext; i<len-1; ++i,p=p->pNext)
	{
		for(j=i+1,q=p->pNext; j<len; j++,q=q->pNext)
		{
			if(p->data > q->data)		//类似于数组中的if(a[i]>a[j])
			{
				t = p->data;			//t=a[i];
				p->data = q->data;		//a[i]=a[j];		
				q->data= t;				//a[j]=t;
			}
		}
	}
}
//在pos个前插入一个新节点
bool insert_list(PNODE pHead, int pos, int val)
{
	int i = 0;

	PNODE p = pHead;

	while(NULL!=p && i<pos-1)	//精要
	{
		p = p->pNext;
		++i;
	}
	if(i>pos-1 || NULL==p)
		return false;

	PNODE  pNew = (PNODE)malloc(sizeof(PNODE));
	if(NULL == pNew)
	{
		printf("动态内存分配失败!\n");	
		exit(-1);
	}
	pNew->data = val;
	PNODE q =p ->pNext;
	p->pNext= pNew;
	pNew->pNext =q;

	return true;

}
bool delete_list(PNODE pHead, int pos, int * pVal)	//最后一个删除值
{
	int i = 0;

	PNODE p = pHead;

	while(NULL!=p->pNext && i<pos-1)	//精要
	{
		p = p->pNext;
		++i;
	}
	if(i>pos-1 || NULL==p->pNext)
		return false;

	PNODE q = p->pNext;
	*pVal = q->data;

	p->pNext = p->pNext->pNext;
	q=NULL;
	free(q);

	return true;
}
小结
数据的存储结构
线性
连续存储【数据】
离散存储【链表】
非线性






连续存储【数组】
优点
存取速度快
缺点
需知道数组长度
插入删除元素慢
插入元素慢
需要大快内存
插入删除元素效率低
离散存储【链表】
优点
空间没有限制
插入删除元素快
缺点
存取速度慢



数据结构
狭义:
数据结构是专门研数据存储的问题
数据的存储包含两方面:个体的存储和个体关系的存储
算法是对存储数据的操作
广义:
数据的存储和操作
算法
狭义;
算法和数据的存储方式密切相关
广义
算法和数据的存储方式无关
泛型思想

你可能感兴趣的:(数据结构,链表,数组,存储)