1、连续存储(数组)
int a[10];
int *pArr = (*int
1)什么叫数组
元素类型相同,大小相等。
2)数组的优缺点
优点:存取速度快
缺点:事先必须知道数组的长度,插入删除元素慢,空间通常是有限制,需要大块连续内存。
练习代码见:数据结构数组算法.c
确定一个数组需要几个信息:
数组首地址
数组长度
有效位数
2、离散存储(链表)
1)链表优缺点:
优点:空间没有限制,插入删除元素快
缺点:存取速度很慢。
2)预备知识:typedef的用法:
typedef struct Student
{
int sid;
char name[100];
char sex;
}*PST,ST; //ST等价于struct Student,PST等价于:struct Student *
//给 struct Student类型的指针PST
//此时PST等价于:struct Student * 是一个指针
树与图都是靠链表实现的,所以,链表非常重要。
3)定义:
n个节点离散分配
彼此通过指针相连
每个节点只有一个前去节点,每个节点只有一个后续节点。
首节点没有前驱结点,尾节点没有后续节点。
专业术语:
首节点:
第一个有效节点
尾节点:
最后一个有效节点,指向下一个元素的指针为空。
头节点:
头节点数据类型与首节点数据类型相同
第一个有效节点前的节点
不存放有效数据
目的主要是为了方便对链表的操作。
头指针:
指向头结点的指针变量
尾指针:
指向尾节点的指针变量
如果希望通过一个函数来对链表进行处理,我们至少徐亚接收链表的那些参数(确定一个链表需要几个参数):
只需要一个参数:头指针
因为我们通过头指针可以推算出链表的其他所有信息。
链表的定义:
typedef struct Node
{
int data; //数据域
struct Node *pNext; //指针
}NODE,*PNODE; //NODE等价于struct Node, PNODE等价于struct Node *
4)分类:
单链表:
双链表:
每个节点有两个指针域,指向前一个与后一个节点。
循环链表:
能通过任何一个节点找到其他所有的节点。
非循环链表:
5)算法:
遍历
查找
清空
销毁
求长度
排序
删除节点:
p->pNext = p->pNext->pNext; //内存泄漏(p后边节点的内存没释放)
不能free(p->pNext);
正确做法:
r = p->pNext; //r指向p后面的那个节点
p->pNext = r->pNext;
free(p->->pNext);
插入节点:
将新的节点q插入链表中p的后边:
r = p->pNext; p->pNext = q; q->pNext = r ;
或:q->pNext = p->pNext; p->pNext = q;
算法:
狭义的算法与数据存储方式密切相关
广义的算法与数据存储方式无关
泛型:
利用某种技术达到的效果就是:不同的存储方式,执行的操作时一样的。
学算法,最重要的不是自己编算法,重要的是看懂已有的算法。重要的是看懂答案。
3、线性结构的两种常见结构一:栈
定义
一种可以实现“先进后出”的存储结构
栈类似于箱子,
分类
静态栈
动态栈(用的较多)
算法
出栈
压栈
每次压栈都压入栈顶
应用
函数调用
中断
表达式求职
内存分配
缓冲处理
迷宫
4、线性结构的两种常见结构二:队列
5、专题:递归
1)1+2+3+4….100的和(递归与循环的转换)
2)求阶乘
3)汉诺塔
4)走迷宫
6、相关代码:
1//链表操作代码
2//数据存储位置相关代码
3//栈操作相关代码
//链表操作代码
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
struct Node
{
int data; //数据与
struct Node *pNext; //指针域
}NODE ,*PNODE; //NODE 等价于struct Node PNODE等价于struct Node*
//函数声明
PNODE create_list(void); //创建链表
void traverse_list(PNODE pHead); //遍历链表
bool is_empty(PNODE pHead); //判断链表为空
int length_list(PNODE); //判断链表长度
bool insert_list(PNODE,int,int); //插入
//在pHead所指向链表的第pos个节点的前面插入一个新的节点,该节点的值是val,并且pos的值从1开始。
bool delete_list(PNODE,int,int *); //删除
void sort_list(PNODE); //排序
int main(void)
{
PNODE pHead = NULL; //等价于struct Node* pHead = NULL;
pHead = create_list() //创建一个非循环单链表,并将该链表的头结点的地址赋给pHead
traverse_list(pHead); //遍历链表
//输出链表长度
int len = length_list(pHead);
printf("链表长度是%d",len);
//判断链表是否为空
if(is_empty(PNODE))
printf("链表为空");
else
printf("链表不为空");
sort_list(pHead); //排序
traverse_list(pHead); //遍历链表
return 0;
}
PNODE create_list(void)
{
int len,i,val;
//分配了一个不存放有效数据的头节点
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if(NULL == pHead)
{
printf("分配失败");
exit(-1);
}
//定义一个指向尾节点的指针
PNODE pTail = pHead;
pTail->pNext = NULL;
printf("输入要生成链表节点的个数 : len = ");
scanf("%d",%len);
for(i=0;i<len;i++)
{
printf("请输入第%d个节点的值:",i+1);
scanf("%d",&val);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(NULL == pNew)
{
printf("分配失败");
exit(-1);
}
pNew->data = val;
pTail->pNext = pNew;
pNew->pNext = 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");
return;
}
bool is_empty(PNODE pHead)
{
if(NULL == pHead->pNext)
return true;
else
return false;
}
int length_list(PNODE pHead)
{
PNODE p = pHead->pNext;
int cnt;
while(NULL!=p)
{
cnt ++;
p= p->pNext;
}
return cnt;
}
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->pNext)
{
t = p->data; //类似于t=a[i];
p->data = q->data; //类似于a[i]=a[j];
q->data = t; //类似于a[j]=t;
}
}
}
}
//在pHead所指向链表的第pos个节点的前面插入一个新的节点,该节点的值是val,并且pos的值从1开始。
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;
}//指针p指向第pos个或最后一个节点。
if(i>pos-1 || NULL = p)//pos小于1或pos大于链表长度
return false;
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(NULL== pNew)
{
printf("动态分配内存失败!");
exit(-1);
}
pNew->data = val;
// pNew插入链表中
PNODE q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;
retuen 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;
}//指针p指向第pos-1个或最后一个节点。
if(i>pos-1 || NULL = p->pNext)//pos小于1或pos大于链表长度
return false;
PNODE q = p->pNext;
*pVal = q->data;
//删除p节点后边的节点
p->pNext = p->pNext->pNext;
free(q);
q = NULL;
retuen true;
}
//数据存储位置相关代码
#include<stdio.h>
#include<malloc.h>
void f(int k)
{
int m;
double *q = (doble *)malloc(200);
}
int main(void)
{
int i = 10;
int *p = (int *)malloc(100);
return 0;
}
//代码中 i、p、m、q,在栈里分配
//malloc开辟的100个,200个内存在堆里分配
//栈里的内存程序自动分配,动态内存需要程序员手动分配
//栈操作相关代码
/*
创建
压栈
出栈
遍历
清空
*/
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct Node
{
intdata;
struct Node *pNext;
}NODE, * PNODE;
struct Stack
{
PNODE pTop; //指向栈顶
PNODE pBottom; //指向栈底
}STACK,* PSTACK;
void init(PSTACK);
void push(PSTACK pS,int val);
void traverse(PSTACK);
bool pop(PSTACK,int *); //出栈
void clear(PSTACK pS); //框架还在,里边的元素都没了
int main(void)
{
STACK S;
int val;
init(&S); // 初始化
push(&S,1); //压栈,不能指定位置,只能压栈到栈底
push(&S,2); //压栈
traverse(&S); //遍历输出
clear(&S); //清空
traverse(&S); //遍历输出
if(pop(&S,&val)) //出栈
{
printf("出栈成功,出栈元素是%d\n",val);
}
else
{
printf("出栈失败");
}
return 0;
}
void init(PSTACK pS)
{
pS->pTop = (PNODE)malloc(sizeof(NODE)); //栈顶,头结点(无数据节点)
if(NULL == pS->pTop)
{
printf("分配失败");
}
else
{
pS->pBottom = pS->pTop;
pS->pTop->pNext = NULL; //pS->Bottom->pNext = NULL
}
}
void push(PSTACK pS,int val)
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));
pNew->data = val;
pNew->pNext = pS->pTop; //新节点插入到原栈顶上方
pS->pTop = pNew; //新节点成为栈顶
return;
}
void traverse(PSTACK pS)
{
PNODE p = pS->pTop;
while(p != pS->pBottom)
{
printf("%d ",p->data);
p=p->pNext;
}
printf("\n");
retrun ;
}
bool empty(PSTACK pS)
{
if(pS->pTop == pS->pBottom)
return true;
else
return false;
}
//把pS所指向的栈出栈一次,并把出战的元素存入pVal形参所指向的变量中,
bool pop(PSTACK pS,int *pval) //出栈
{
if(empty(pS))
{
return false;
}
else
{
PNODE r = pS->pTop;
*pval = r->data;
pS->pTop = r->pNext;
free(r);
r = NULL;
return true;
}
}
void clear(PSTACK pS) //框架还在,里边的元素都没了
{
if(empty(pS))
{
return ;
}
else
{
PNODE p = pS->pTop;
PNODE q = p->pNext;
while(p!=pS->pBottom)
{
q=p->pNext;
free(p);
p = q;
}
pS->pTop = pS->pTop;
}
/*自己写的代码
PNODE r;
while(NULL != pS->pTop )
{
r = pS->pTop;
pS->pTop = r->pNext;
free(r);
}
*/
}