数据结构总结:
算法+数据结构=程序(算法是解决问题的方法和步骤,数据结构是管理数据的一种机制)
批量同类的数据管理的机制,即如何管理和组织数据结构,在什么样的数据结构上采用什么样的算法。
研究数据的逻辑结构(即元素间的逻辑关系),物理结构(存储方式),基于上面2个方面的各种操作(插入、移除、查找、排序)的实现方式。
1、(1)栈:先进后出 (2)队列:先进先出 (3)树:一对多(4):多对多
2、存储方式(1)顺序存储(2)链式存储:也是一对一,每个数据的性质都是一样的,每个数据中都唯一的存放着下一个数据的 地址
(3)索引存储
3、链表 :头指针:是一个指针变量,保存第一个节点在内存空间的首地址
头节点:是一个与节点类型不一样的特殊对象,是另一种结构类型,数据域是一些体现链表整体的一些属性,如表长,指针域至少一个用于保存第一个结点的地址,也就是头指针。
利用头节点在内存空间的地址就可以代表整个地址,即代表一个有头节点的地址。(叫做有头节点的链表)
没有头节点的的链表可以用一个指针变量来存储链表第一个结构体的地址叫头指针(头指针链表)
单向链表:指针域指针直接指向下一个结构体
双向链表:双向链表的指针域,一个指针指向下一个结构体地址,另一个指向一个结构体的地址
循环链表:单向链表的最后一个结构体存第一个结构体的地址,双项链表最后一个结构体的指针域第一个值存第一个结构体的地址,第二个指针域存的是上一个结构体的地址。第一个节点的指针域的第一个指针(pstnext指针域)存第二个节点的地址,第二个指针(pstprev指针域)存最后一个结点的地址。
4、单向链表操作程序:
5、双向链表操作程序:
链表表示:图书管理系统。
#include<stdio.h>
#inlcude<stdlib.h>
#include<string.h>
struct BookNode//定义结点结构体
{
char name[20];
float price;
char author[20];
int num;
struct BookNode *pstNext;
struct BookNode *pstPrev;
};
struct BLHead//定义头结点结构体
{
int len;
struct BookNode *pstFirst;
};
struct BookNode *CreateBookNode(struct BookNode *Bookdata)
{
struct BookNode *pstNode=NULL;
pstNode=(struct BookNode *)malloc(sizeof(strcut BookNode));
if(NULL==pstNode)
{
return NULL;
}
if(BookData==NULL)
{
memset(pstNode,0,sizeof(struct BookNode));
}
else
{
memcpy(pstNode,Bookdata,sizeof(struct BookNode));
pstNode->pstNext=NULL;
pstNode->pstPrev=NULL;
}
return pstNode;
}
int DestroyBookNode(struct BookNode *pstNode)
{
if(pstNode!=NULL)
{ free(pstNode);
pstNode==NULL;
}
}
//创建了一个头结点
struct BookNode *CreateBLHead()
{
struct BLHeade *pstNode=NULL;
pstNode=(struct BLHead *)malloc(sizeof(strcut BLHead));
if(NULL==pstNode)
{
return NULL;
}
memset(pstNode,0,sizeof(struct BLHead));
return pstNode;
}
int DestroyBLHead(struct BLHead *pstHead)//销毁头结点就是销毁整个链表
{
struct BookNode *pstNode=NULL;
struct BookNode *pstNext=NULL ;
if(NULL==pstHead)
{ return -1;
}
pstNode=pstHeadead->pstFirst;
while(pstNode!=NULL)
{
pstNext=pstNode->pstNext;
DestroyBookNode(pstNext);
pstNode=pstNext;
}
free(pstHead);
pstHead=NULL;
return 0;
}
//在链表的开头节点插入
int InsertNewNodeAF(struct BLHead *pstHead,struct BookNode *pstNew)
{
struct BookNode *pstNode=NULL;
if(NULL==pstHead||NULL==pstNew)
{return -1;}
pstNode=pstHead->pstFirst;
pstHead->pstFirst=pstNew;
pstNew->pstNext=pstNode;
pstNew-pstPrev=NUll;
pstNode->pstPrev=pstNew;
pstHead->len++;
}
//移除一个结点
int RemoveNode(struct BLHead *pstHead,struct BookNode *pstNode)
{ struct BookNode *pstTemp=NULL;//对要移除的节点进行判断,使用到搜索节点功能。
if(pstHead==NULL||pstNew==NULL)
{
return -1;
}
pstTemp=pstHead->pstFirst;
while(pstTemp!=NULL)//判断被移除的节点是否为链表的中的节点
{
if(pstTemp==pstNode)
{break;}
pstTemp=pstTemp->pstNext;
}
if(pstTemp==NULL)
{
retunr -1;
}
if(pstNode->pstPrev!=NULL)
{
pstNode->pstPrev->pstNext=pstNode->pstNext;
}
else//说明被移除的节点是第一个节点
{ pstHead->pstFirst=pstNode->pstNext;
}
if(pstNode->pstNext!=NULL)
{
pstNode->pstNext->pstPrev=pstNode->pstPrev;
}
//至此链表已经脱链
pstNode->pstPrev=NULL;
pstNode->pstNext=NULL;
pstHead->len--;
return 0;
}
struct BookNode *SearchNodeByName(struct BLHead *pstHead,char *name)//按名字查询,返回节点地址
{
struct BookNode *pstNode=NULL;
if(NULL==pstHead||NULL==name)
{
return NULL;
}
pstNode=pstHead->pstFirst;
while(pstNode!=NULL)
{ if(strcmp(pstNode->name,name)==0)
pstNode=pstNode->pstNext;
break;
}
return pstNode;
}
int printAllNode(struct BLHead *pstHead)
{
struct BookNode *pstNode=NULL;
if(NULL==pstHead)
{
return -1;
}
pstNode=pstHead->pstFirst;
while(pstNode!=NULL)
{ printf("BookName:%s Author:%s Price:%.2 Num:%d\n",pstNode->name,pstNode->author,pstNode->price,pstNode->num);
pstNode=pstNode->pstNext;
}
}
int main( int argc,char *argv[])
{
struct BLHead *pstHead=CreateBLHead();
struct BookNode *pstNew=NULL;
struct BookNode bookdata={""};
struct BookNode *pstTemp=NULL;
strcpy(bookdata.name,"SanTi");
strcpy(bookdata.author,"Liucixi");
bookdata.price=86;
bookdata.price=3;
pstNew=CreateBookNode(&bookdata);
InsertNewNodeAF(pstHead,pstNew);//至此第一本书在链表了
strcpy(bookdata.name,"Hongloumeng");
strcpy(bookdata.author,"Caoxueqin");
bookdata.price=36;
bookdata.price=5;
pstNew=CreateBookNode(&bookdata);
InsertNewNodeAF(pstHead,pstNew);
strcpy(bookdata.name,"Xiyouji");
strcpy(bookdata.author,"Wuchengen");
bookdata.price=56;
bookdata.price=4;
pstNew=CreateBookNode(&bookdata);
InsertNewNodeAF(pstHead,pstNew);//链表头部插入
printAllNode(pstHead);
pstTemp=SearchNodeByName(pstHead,SanTi);
if(pstTemp==NULL)
{
printf("Couldn't find");
}
else
{
RemoveNode(pstHead,struct pstTemp);
DestroyBookNode(pstTemp);
}
printAllNode(pstHead);
DestroyBookNode(pstHead);
return 0;
}
以上都是有头结点的指针,对于没有头结点的指针,注意 无头结点的链表
将第一个节点的地址保存到一个指针变量里去pstFirst 不带头结点的链表,在链表的前端插入一个数值的时候往往涉及到二阶指针的操作,因为修改链表的地址值就要对保存第一个节点地址的指针变量进行操作,因此就要知道指针变量的地址是多少。