供参考:
如下面的代码:
#include <stdio.h>
#pragma pack(2)
struct Test1
{
char c1;
short s;
char c2;
int i;
};
#pragma pack()
#pragma pack(4)
struct Test2
{
char c1;
char c2;
short s;
int i;
};
#pragma pack()
int main()
{
printf("sizeof(Test1) = %d\n", sizeof(struct Test1));
printf("sizeof(Test2) = %d\n", sizeof(struct Test2));
return 0;
}
sizeof(Test1) = 10
sizeof(Test2) = 8
对于结构体Test1,2字节对齐,按照上述三个计算条件有:
struct Test1
{ //对齐方式 大小 起始地址 占用的内存地址位置
char c1; 2 大于 1 0 0
short s; 2 等于 2 2(被对齐参数2整除) 2~3
char c2; 2 大于 1(对齐参数) 4 4
int i; 2(对齐参数) 小于 4 6(被对齐参数2整除) 6~9
};
然后根据:
每个成员按其类型大小和pack参数中较小的一个 进行对齐。比如上面的起始地址计算那里,都是被对齐参数2整除,这个2是类型大小和pack参数中较小的一个
2.1 偏移地址必须能被对齐参数整除
这一条规则计算每个成员的起始地址。如上面的计算。
对于结构体Test2,4字节对齐,按照上述三个计算条件有:
struct Test2
{ //对齐方式 大小 起始地址 占用的内存地址位置
char c1; 4 大于 1(对齐参数) 0 0
char c2; 4 大于 1(对齐参数) 1(被对齐参数1整除) 1
short s; 4 大于 2(对齐参数) 2(被对齐参数2整除) 2~3
int i; 4 等于 4(对齐参数) 4(被对齐参数4整除) 5~7
};
然后再根据:
每个成员按其类型大小和pack参数中较小的一个 进行对齐。比如上面的起始地址计算那里,对齐参数分别为1,1,2,4
2.1 偏移地址必须能被对齐参数整除
这一条规则计算每个成员的起始地址。如上面的计算。
经过上面的两个结构体大小的计算,可以很容易的画出其内存图
答案:
删除链表中的第i个元素,需要遍历链表找到第i个元素,并将其从链表中删除。
具体的步骤如下:
struct Node {
int val;
struct Node* next;
};
struct LinkedList {
struct Node* head;
};
void deleteNode(struct LinkedList* list, int index) {
if (list == NULL || list->head == NULL || index < 1) {
return;
}
// 如果要删除头节点
if (index == 1) {
struct Node* p = list->head;
list->head = p->next;
free(p);
return;
}
// 找到待删除节点的前一个节点
struct Node* prev = list->head;
for (int i = 1; i < index - 1 && prev->next != NULL; i++) {
prev = prev->next;
}
// 检查节点是否存在
if (prev->next == NULL) {
return;
}
// 删除节点
struct Node* p = prev->next;
prev->next = p->next;
free(p);
}
int main() {
struct LinkedList list;
struct Node* node1 = (struct Node*)malloc(sizeof(struct Node));
node1->val = 1;
struct Node* node2 = (struct Node*)malloc(sizeof(struct Node));
node2->val = 2;
struct Node* node3 = (struct Node*)malloc(sizeof(struct Node));
node3->val = 3;
node1->next = node2;
node2->next = node3;
node3->next = NULL;
list.head = node1;
printf("before delete: ");
struct Node* p = list.head;
while (p != NULL) {
printf("%d ", p->val);
p = p->next;
}
printf("\n");
deleteNode(&list, 2);
printf("after delete: ");
p = list.head;
while (p != NULL) {
printf("%d ", p->val);
p = p->next;
}
printf("\n");
return 0;
}
输出结果为:
before delete: 1 2 3 after delete: 1 3
注解说明:
在函数deleteNode中,首先进行了一些边界检查,如果链表为空或者index<1就直接返回。然后特判了要删除头节点的情况,直接将头节点指针指向下一个节点,然后释放被删除的节点。接着就从第一个节点开始遍历,遍历到第i-1个节点时即为要删除的节点的前一个节点,然后判断要删除的节点是否存在,如果存在就将删除节点的前一个节点指向删除节点的下一个节点,然后释放被删除的节点。最后在主函数中测试了一下代码,首先遍历输出链表,然后删除第二个节点,最后再遍历输出链表。
数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633