线性结构:【把所有的结点用一根线穿起来】
连续存储【数组】
1.什么叫数组
数组元素类型相同,大小相等
优点:存取速度很快
缺点:插入删除元素很慢,事先必须知道数组的长度
空间通常是有限制的,需要大块连续的内存块
数组的基本操作:
初始化:
void init_arr(struct Arr* pArr, int length)
{
pArr->pBase = (int*)malloc(sizeof(int) * length);
if (pArr == NULL)
{
printf("动态内存分配失败\n");
}
else
{
pArr->len = length;
pArr->cnt = 0;
}
return;
}
添加元素:
bool append_arr(struct Arr *pArr,int val)
{
if (is_full(pArr))
return false;
else
pArr->pBase[pArr->cnt] = val;
pArr->cnt++;
}
插入:
bool insert_arr(struct Arr* pArr,int pos,int val)
{
int i = 0;
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)
{
int i = 0;
if (is_empty(pArr))
return false;
if (pos<1 || pos>pArr->cnt + 1)
return false;
*pVal = pArr->pBase[pos - 1];
for (i = pos; i < pArr->cnt; i++)
{
pArr->pBase[i - 1] = pArr->pBase[i];
}
pArr->cnt--;
return true;
}
冒泡排序:
void sort_arr(struct Arr* pArr)
{
for (int i = 0; i < pArr->cnt; i++)
{
for (int j = i+1; j < pArr->cnt; j++)
{
int temp = 0;
if (pArr->pBase[i] < pArr->pBase[j])
{
temp = pArr->pBase[i];
pArr->pBase[i] = pArr->pBase[j];
pArr->pBase[j] = temp;
}
}
}
}
倒置:
void inversion_arr(struct Arr* pArr)
{
for (int i = 0; i < pArr->cnt/2; i++)
{
for (int j = pArr->cnt-1; j > pArr->cnt / 2; j--)
{
int t = 0;
t = pArr->pBase[i];
pArr->pBase[i] = pArr->pBase[j];
pArr->pBase[j] = t;
}
}
return;
}
显示:
void show_arr(struct Arr *pArr)
{
if (is_empty(pArr))
{
printf("数组为空\n");
}
else
{
for(int i = 0;i<pArr->cnt;i++)
{
printf("%d \n", pArr->pBase[i]);
}
}
}
离散存储【链表
定义:
n个节点离散分配
彼此通过指针相连
每个节点只有一个前驱节点,每个节点只有一个后续节点
首节点没有前驱节点 尾节点没有后续节点
优点:空间没有限制,插入删除元素很快
缺点:存取速度很慢
专业术语:
首节点:第一个有效节点
尾节点:最后一个有效节节点
头节点:头节点的数据类型和首节点类型一样
第一个有效节点之前的那个节点是头节点
头节点并不存放数据
加头节点的目的主要是为了方便对来年表的操作
头指针:指向头节点的指针变量
尾指针:指向尾节点的指针变量
如果希望通过一个函数来对链表进行处理,我们至少需要接受链表的哪些参数:
只需要一个参数:头指针,通过头指针可以推算出链表的其他所有参数
分类:
单链表
双链表:每一个节点有两个指针域
循环链表:能通过任何一个节点找到其他所有节点
非循环链表
链表基本操作:
创建链表:
PNODE create_list(void)
{
int len; //用来存放有效节点的个数
int i;
int val; //用来临时存放用户输入的结点的值
//分配了一个不存放有效数据的头结点
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if (NULL == pHead)
{
printf("分配失败, 程序终止!\n");
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("分配失败, 程序终止!\n");
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;
}
长度:
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;
int len = length_list(pHead);
PNODE p, q;
for (p = pHead->pNext;p!=NULL; p = p->pNext)
{
for (q = pHead->pNext; q!=NULL;q = q->pNext)
{
if (q->pNext != NULL)
{
if (p->data > q->data) //类似于数组中的: a[i] > a[j]
{
t = p->data;//类似于数组中的: t = a[i];
p->data = q->data; //类似于数组中的: a[i] = a[j];
q->data = t; //类似于数组中的: a[j] = t;
}
}
}
}
return;
}
插入:
/在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;
}
if (i>pos-1 || NULL==p)
return false;
//如果程序能执行到这一行说明p已经指向了第pos-1个结点,但第pos-1个节点是否存在无所谓
//分配新的结点
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("动态分配内存失败!\n");
exit(-1);
}
pNew->data = val;
//将新的结点存入p节点的后面
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;
//如果程序能执行到这一行说明p已经指向了第pos-1个结点,并且第pos个节点是存在的
PNODE q = p->pNext; //q指向待删除的结点
*pVal = q->data;
//删除p节点后面的结点
p->pNext = p->pNext->pNext;
//释放q所指向的节点所占的内存
free(q);
q = NULL;
return true;
}