-----------------------------------------------第一次作业--------------------------------------------------------------------------
1:什么是链表
动态分配存储结构,不会造成空间的浪费。链表有一个人头指针,通过头指针访问链表中其他的元素,除头指针外,剩余的为结点,每一个节点中有数据成员还有下一个节点元素的地址,通过地址访问下一个节点,所以,链表不像线性表一样是顺序存储结构。
2:链表的增删改查
#include<ctype.h>
#include<malloc.h>
#include<stdio.h>
#include<stdlib.h>
#include<process.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
/*结构体的定义 */
struct LNode
{
ElemType data;
struct LNode *next;
};
typedef struct LNode *LinkList;
/*创建一个新的链表*/
void InitList(LinkList *L)
{
*L = (LinkList)malloc(sizeof(struct LNode));
if (!*L)
exit(OVERFLOW);
(*L)->next = NULL;
}
/*链表的销毁*/
void DestroyList(LinkList *L)
{
LinkList q;
while (*L)
{
q = (*L)->next;
free(*L);
*L = q;
}
}
/*链表的增加操作*/
Status ListInsert(LinkList L, int i, ElemType e)
{
int j = 0;
LinkList p = L, s;
while (p&&j<i - 1)
{
p = p->next;
j++;
}
if (!p || j>i - 1)
s = (LinkList)malloc(sizeof(struct LNode));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
/*链表的删除操作*/
Status ListDelete(LinkList L, int i, ElemType *e)
{
int j = 0;
LinkList p = L, q;
while (p->next&&j<i - 1)
{
p = p->next;
j++;
}
if (!p->next || j>i - 1)
return ERROR;
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
/*链表的改变*/
Status ListChange(LinkList L, int i, ElemType *e)
{
int j = 0;
LinkList p = L->next;
while (p&&j <i - 1)
{
p = p->next;
j++;
}
if (!p || j > i - 1)
return ERROR;
p->data = *e;
return OK;
}
/*链表的访问*/
void ListTraverse(LinkList L)
{
LinkList p = L->next;
while (p)
{
printf("%3d", p->data);
p = p->next;
}
printf("\n");
}
/*主函数*/
void main()
{
LinkList L;
ElemType e;
Status i;
int j;
int num;
InitList(&L);
for (j = 1; j <= 5; j++)
i = ListInsert(L, 1, j);
printf("在L的表头依次插入1~5后:L=");
ListTraverse(L);
printf("输入要改变元素的值:");
scanf_s("%d",&num);
i = ListChange(L,2,&num);
printf("改变链表元素以后的链表\n");
ListTraverse(L);
i = ListDelete(L, 4, &e);
if (i == ERROR)
printf("删除元素失败\n");
else
printf("删除元素成功,其值为:%d\n", e);
printf("依次输出删除后L的元素:");
ListTraverse(L);
DestroyList(&L);
}
链表中的数据结构如何分配内存单元
程序的内存可以划分为堆区,栈区,静态区,代码区。栈区编译器自动分配释放,存放函数参数,局部变量等。堆区是动态分配,由程序员完成。静态区存放全局变量和静态变量,程序结束后系统释放。代码区存放程序代码。数据结构中的链表是动态分配,需要用malloc申请内存,用delete释放内存。
树和二叉树
1:树的定义:树是n(n≥0)个结点的有限集合。若n=0,则称为空树;否则,有且仅有一个特定的结点被称为根,当n>1时,其余结点被分成m(m>0)个互不相交的子集T1,T2,...,Tm,每个子集又是一棵树。由此可以看出,树的定义是递归。
二叉树的定义:每个结点至多只有两棵子树(即不存在大于2的结点),且二叉树的子树有左右之分,其次序不能任意颠倒。
2:有几种树:有向树,二叉树
3:树的应用:树与二叉树的转换的实现、树的前序、后序的递归
4:简单的二叉树排序树:
#include<malloc.h>
#include<process.h>
#include<stdlib.h>
#include<ctype.h>
#define OK 1
#define ERROR 0
#define FALSE 0
#define TRUE 1
#define OVERFLOW -2
typedef int ElemType;
typedef int Status;
/*双向链表中结构体的定义*/
typedef struct DuLNode {
ElemType data;
struct DuLNode *prior;
struct DuLNode *next;
}NuLNode,*DuLinkList;
/*建立空的双向链表*/
void InitList(DuLinkList *L)
{
(*L) = (DuLinkList)malloc(sizeof(struct DuLNode));
if (!*L)
exit(OVERFLOW);
(*L)->next = NULL;
}
/*链表的增加操作*/
Status ListInsert(DuLinkList L, int i, ElemType e)
{
int j = 0;
DuLinkList q,p=L;
q = (DuLinkList)malloc(sizeof(struct DuLNode));
while (p&&j < i - 1)/*指向第i个元素*/
{
p = p->next;
j++;
}
q->data = e;
q->next = p->next;
p->next = q;
p->next->prior = q;
q->prior = p;
return OK;
}
/*链表的删除操作*/
Status ListDelect(DuLinkList L, int i, ElemType *e)
{
int j = 0;
DuLinkList q, p=L;
while (p->next&&j < i - 1)
{
p = p->next;
j++;
}
q = p->next;
p->next = q->next;
q->next->prior = p;
*e = p->data;
free(q);
return OK;
}
Status ListChange(DuLinkList L, int i, ElemType *e)
{
int j = 0;
DuLinkList p = L->next;
while (p&&j <i - 1)
{
p = p->next;
j++;
}
if (!p || j > i - 1)
return ERROR;
p->data = *e;
return OK;
}
void Traverse(DuLinkList L)
{
DuLinkList p = L->next;
while (p)
{
printf("%d", p->data);
p = p->next;
}
printf("\n");
}
/*主函数*/
void main()
{
ElemType e;
int i,j,num;
DuLinkList L;
InitList(&L);
for (j = 0; j < 5; j++)
i = ListInsert(L, 1, j);
printf("输入插入元素以后的双向链表元素:");
Traverse(L);
printf("输入要改变元素的值:");
scanf_s("%d", &num);
i = ListChange(L, 2, &num);
printf("改变链表元素以后的链表\n");
Traverse(L);
i = ListDelect(L, 4, &e);
printf("输出删除元素以后的链表:");
Traverse(L);
}
#include<malloc.h>
#include<stdio.h>
#include<stdlib.h>
#include<process.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
/*结构体的定义 */
struct LNode
{
ElemType data;
struct LNode *next;
};
typedef struct LNode *LinkList;
/*创建一个新的链表*/
void InitList(LinkList *L)
{
*L = (LinkList)malloc(sizeof(struct LNode));
if (!*L)
exit(OVERFLOW);
(*L)->next = NULL;
}
/*链表的销毁*/
void DestroyList(LinkList *L)
{
LinkList q;
while (*L)
{
q = (*L)->next;
free(*L);
*L = q;
}
}
/*链表的增加操作*/
Status ListInsert(LinkList L, int i, ElemType e)
{
int j = 0;
LinkList p = L, s;
while (p->next!=L&&j<i-1)
{
p = p->next;
j++;
}
if (p->next==L || j>i - 1)
return ERROR;
s = (LinkList)malloc(sizeof(struct LNode));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
/*链表的删除操作*/
Status ListDelete(LinkList L, int i, ElemType *e)
{
int j = 0;
LinkList p = L, q;
while (p->next->next!=L&&j<i - 1)
{
p = p->next;
j++;
}
if (!p->next || j>i - 1)
return ERROR;
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
/*链表的改变*/
Status ListChange(LinkList L, int i, ElemType *e)
{
int j = 0;
LinkList p = L->next;
while (p->next!=L&&j <i - 1)
{
p = p->next;
j++;
}
if (p->next==L|| j > i - 1)
return ERROR;
p->data = *e;
return OK;
}
/*链表的访问*/
void ListTraverse(LinkList L)
{
LinkList p = L->next;
while (p->next!=L)
{
printf("%3d", p->data);
p = p->next;
}
printf("\n");
}
/*主函数*/
void main()
{
LinkList L;
ElemType e;
Status i;
int j;
int num;
InitList(&L);
for (j = 1; j <= 5; j++)
i = ListInsert(L, 1, j);
printf("在L的表头依次插入1~5后:L=");
ListTraverse(L);
printf("输入要改变元素的值:");
scanf_s("%d", &num);
i = ListChange(L, 2, &num);
printf("改变链表元素以后的链表\n");
ListTraverse(L);
i = ListDelete(L, 4, &e);
if (i == ERROR)
printf("删除元素失败\n");
else
printf("删除元素成功,其值为:%d\n", e);
printf("依次输出删除后L的元素:");
ListTraverse(L);
DestroyList(&L);
}
#include<malloc.h>
#include<process.h>
#include<stdlib.h>
#include<ctype.h>
#define OK 1
#define ERROR 0
#define FALSE 0
#define TRUE 1
#define OVERFLOW -2
typedef int ElemType;
typedef int Status;
/*双向链表中结构体的定义*/
typedef struct DuLNode {
ElemType data;
struct DuLNode *prior;
struct DuLNode *next;
}NuLNode, *DuLinkList;
/*建立空的双向链表*/
void InitList(DuLinkList *L)
{
(*L) = (DuLinkList)malloc(sizeof(struct DuLNode));
if (!*L)
exit(OVERFLOW);
(*L)->next = NULL;
}
/*链表的增加操作*/
Status ListInsert(DuLinkList L, int i, ElemType e)
{
int j = 0;
DuLinkList q, p = L;
q = (DuLinkList)malloc(sizeof(struct DuLNode));
while (p->next!=L&&j < i - 1)/*指向第i个元素*/
{
p = p->next;
j++;
}
q->data = e;
q->next = p->next;
p->next = q;
p->next->prior = q;
q->prior = p;
return OK;
}
/*链表的删除操作*/
Status ListDelect(DuLinkList L, int i, ElemType *e)
{
int j = 0;
DuLinkList q, p = L;
while (p->next->next!=L&&j < i - 1)
{
p = p->next;
j++;
}
q = p->next;
p->next = q->next;
q->next->prior = p;
*e = p->data;
free(q);
return OK;
}
Status ListChange(DuLinkList L, int i, ElemType *e)
{
int j = 0;
DuLinkList p = L->next;
while (p->next!=L&&j <i - 1)
{
p = p->next;
j++;
}
if (!p || j > i - 1)
return ERROR;
p->data = *e;
return OK;
}
void Traverse(DuLinkList L)
{
DuLinkList p = L->next;
while (p->next!=L)
{
printf("%d", p->data);
p = p->next;
}
printf("\n");
}
/*主函数*/
void main()
{
ElemType e;
int i, j, num;
DuLinkList L;
InitList(&L);
for (j = 0; j < 5; j++)
i = ListInsert(L, 1, j);
printf("输入插入元素以后的双向链表元素:");
Traverse(L);
printf("输入要改变元素的值:");
scanf_s("%d", &num);
i = ListChange(L, 2, &num);
printf("改变链表元素以后的链表\n");
Traverse(L);
i = ListDelect(L, 4, &e);
printf("输出删除元素以后的链表:");
Traverse(L);
}
bb: 大部分总线以BURST为单位读内存,burst通常大于一个字节,不对齐访问会让访问速度变慢
cc:cache读入一般以cacheline为单位更新。不对齐会占有多余cacheline。一般来说,会用cacheline为单位对齐,这样其他问题也得到相应权衡 ,linux内核还会提供这样功能的宏。考虑到pollution,对其的技巧就更复杂了。
dd:便于管理
d. 继续完成编写简单的二叉排序树,并了解hash散列问题。