您的位置:首页 > 理论基础 > 数据结构算法

【数据结构】单向线性链式物理结构list

2017-01-14 20:41 330 查看
【数据结构和算法】

数据结构主要研究的是怎么使用存储区(4 day)

算法研究的是解决一些常见问题的通用方法(1 day)

可以从两个完全不同的角度描述数字之间的关系:

1. 逻辑关系(逻辑结构)描述的是数字之间与计算机无关的关系

2. 物理关系(物理结构)描述的是记录数字的存储区之间的关系

【逻辑结构】分成如下几种:

1. "集合结构":所有数字可以看作是一个整体(菜市场成捆零售的蔬菜)最弱

2. "线性结构":可以用一条有顺序的线把所有数字连起来

3. "树状结构":所有数据都是从一个数据向一个方向方向出来的,任何数据可以扩展出多个其他数据

4. "网状结构":任何两个数据之间都可以有直接的联系,不同数据之间的联系没有统一的方向

【物理结构】有如下几种:

1. "顺序结构":"所有存储区在内存里连续排列"

顺序结构的例子,"数组"/"动态分配内存"

顺序结构中每个存储区都有一个编号

顺序结构里可以直接根据编号找到对应的存储区,这叫做"随机访问能力"

顺序物理结构很难调整大小,容易造成内存浪费

顺序物理结构不是和进行插入或者删除数字的操作

<从数组中正常情况添加和删除数据>
/*代码*/   "随机访问可用"
#include <stdio.h>
int *remov_num(int *p_num, int size, int num) {
int num1 = 0;
for(num1 = 0; num1 < size; num1++) {
if(*(p_num + num1) > num) {
*(p_num + num1 - 1) = *(p_num + num1);
}
else if (num1 && *(p_num + num1) < *(p_num + num1 - 1)) {
*(p_num + num1 - 1) = 0;
break;
}
}
*(p_num + size - 1) = 0;
return p_num;
}
int *insert(int *p_num, int size, int num) {
int num1 = 0, num2 = num, tmp = 0;
for(num1 = 0; num1 < size; num1++) {
if(*(p_num + num1) > num2) {
tmp = *(p_num + num1);
*(p_num + num1) = num2;
num2 = tmp;
}
else if(num1 && *(p_num + num1) < *(p_num + num1 - 1)) {
*(p_num + num1) = num2;
return p_num;
}
}
}
int main() {
int arr[10] = {3, 7, 11, 14, 17, 21, 26, 30, 35, 38};
insert(arr, 10, 16);
remov_num(arr, 10, 11);
int num = 0;
for(num = 0; num < 10; num++) {
printf("%d ", arr[num]);
}
return 0;
}


2. "链式结构":由多个相互独立的存储区构成,任何两个存储区之间可以采用指针连接

链式物理结构中每个存储区都是结构体类型存储区,他们叫做"节点"

"单向线性链式物理结构"任何两个节点之间都有前后顺序(每个节点里只需要包含一个指针)

单向线性链式物理结构中最后一个节点里的指针必须是空指针 NULL

链式物理结构"不支持随机访问能力"

可以在单向线性链式物理结构第一个节点前加一个无效节点,叫做"头节点"

可以在单向线性链式物理结构最后一个节点后加一个无效节点,叫做"尾节点"

<物理结构打印/获取其中1个/插入/删除节点数据>
/*代码*/
#include <stdio.h>
typedef struct Node {
int num;
struct Node *p_next;
} Node;
int main() {
Node node1 = {1}, node2 = {3}, node3 = {5}, node4 = {2};
Node head = {0}, tail = {0}, *p_node = NULL;
int cnt = 0;
head.p_next = &node1;
node1.p_next = &node2;
node2.p_next = &node3;
node3.p_next = &tail;
for(p_node = &head; p_node != &tail; p_node = p_node->p_next) {
Node *p_first = p_node;
Node *p_mid = p_first->p_next;
Node *p_last = p_mid->p_next;
if(p_mid != &tail) {
printf("%d ", p_mid->num); //打印
}
}
printf("\n");
for(p_node = &head; p_node != &tail; p_node = p_node->p_next) {
Node *p_first = p_node;
Node *p_mid = p_first->p_next;
Node *p_last = p_mid->p_next;
if(cnt == 2) {
printf("数字是%d\n", p_mid->num); //打印获取的其中1个
break;
}
cnt++;
}
for(p_node = &head; p_node != &tail; p_node = p_node->p_next) {
Node *p_first = p_node;
Node *p_mid = p_first->p_next;
Node *p_last = p_mid->p_next;
if(p_mid == &tail || p_mid->num > node4.num) {
p_first->p_next = &node4; //地址放在前一个指针地址
node4.p_next = p_mid; //插入一个值
break;
}
}
for(p_node = &head; p_node != &tail; p_node = p_node->p_next){
Node *p_first = p_node;
Node *p_mid = p_first->p_next;
Node *p_last = p_mid->p_next;
if(p_mid != &tail && p_mid->num == 3) {
p_first->p_next = p_last; //删除节点数据,挂接下一个即可
break;
}
}
for(p_node = &head; p_node != &tail; p_node = p_node->p_next) {
Node *p_first = p_node;
Node *p_mid = p_first->p_next;
Node *p_last = p_mid->p_next;
if(p_mid != &tail) {
printf("%d ", p_mid->num); //删除节点数据后再次打印
}
}
printf("\n");
return 0;
}


<动态分配内存实现单向线性链式物理结构>
/*代码*/ "第一个正式的链式物理结构"
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int num;
struct Node *p_next;
} Node;
int main() {
Node *p_node = NULL, *p_tmp = NULL;
Node head = {0}, tail = {0};
head.p_next = &tail;
int num = 0;
while(1) {
printf("请输入一个正数:");
scanf("%d", &num);
if(num < 0) {
break;
}
p_node = (Node *)malloc(sizeof(Node));
if(!p_node) {
continue; //如果动态内存分配失败就跳过,重新分配
}
p_node->num = num;
p_node->p_next = NULL;
for(p_tmp = &head; p_tmp != &tail; p_tmp = p_tmp->p_next) {
/*p_tmp指针循环变量依次和头结点到最后一个有效节点之间的每个节点捆绑,p_first,p_mid,p_last三个指针和三个相邻>节点捆绑,p_first最前,p_mid中间,p_last最后,p_mid永远不为NULL*/
Node *p_first = p_tmp;
Node *p_mid = p_first->p_next;
Node *p_last = p_mid->p_next;
if(p_mid == &tail || p_mid->num > num) {
/*当p_mid和尾节点捆绑(说明p_mid->num比所有数都大) 或 p_mid捆绑节点里的数比新数字大的时候,p_first 和 p_mid中间就是插入位置*/
p_first->p_next = p_node; //p_node即&num
p_node->p_next = p_mid;
break;
}
}
}
for(p_tmp = &head; p_tmp != &tail; p_tmp = p_tmp->p_next) {
Node *p_first = p_tmp;
Node *p_mid = p_first->p_next;
Node *p_last = p_mid->p_next;
if(p_mid != &tail) {
printf("%d ", p_mid->num);
}
}
printf("\n");
/*在循环里反复删除第一个有效节点直到头节点后面是尾节点为止,这样就可以把所有有效节点数据的动态内存释放*/
while(head.p_next != &tail) {
/*p_first,p_mid,p_last永远与最前边的三个节点捆绑,p_mid指针捆绑的就是第一个有效节点,每次循环都释放它*/
Node *p_first = &head;     //p_first与头节点地址绑定
Node *p_mid = p_first->p_next;
Node *p_last = p_mid->p_next;
p_first->p_next = p_last;
free(p_mid);
p_mid = NULL;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构