文章目录
Lecture 7 链表
1. 可变数组
//array.h
#ifndef _ARRAY_H_
#define _ARRAY_H_
typedef struct {
int *array;
int size;
} Array;
Array array_create(int init_size);
void array_free(Array *a);
int array_size(const Array *a);
int* array_at(Array *a, int index);
void array_inflate(Array *a, int more_size);
#endif
1.1 可变数组
the Interface
Array array_create(int init_size)
{
Array a;
a.array = (int*)malloc(sizeof(int)*init_size);
a.size = init_size;
return a;
}
void array_free(Array *a)
{
free(a->array);
a->array = NULL;
a->size = 0;
}
1.2 可变数组的数据访问
//封装
int array_size(const Array *a)
{
return a->size;
}
int* array_at(Array *a, int index)
{
if ( index >= a->size ) {
array_inflate(a, (index/BLOCK_SIZE+1)*BLOCK_SIZE-a->size); //BLOCK_SIZE=20;
}
return &(a->array[index]);
}
1.3 可变数组的自动增长
void array_inflate(Array *a, int more_size)
{
int *p = (int*)malloc(sizeof(int)*(a->size + more_size))
int i;
for ( i=0; i<a->size; i++) {
p[i] = a->array[i];
} //此循环可替换为标准库函数:memcpy,提高效率
free(a->array);
a->array = p;
a->size += more_size;
}
1.4 主函数
//array.c
#include "array.h"
#include <stdio.h>
#include <stdlib.h>
const BLOCK_SIZE = 20;
int main()
{
Array a = array_create(100); //创建初始数组
*array_at(&a,0) = 10; //给第一个元素赋值
int number=0;
int cnt=0;
while(number != -1) {
scanf("%d", &number);
if (number != -1)
*array_at(&a, cnt++)=number; //写入当前位置
}
array_free(&a);
return 0;
}
2. 链表
2.1 可变数组的缺陷
- 数组增长时,每次拷贝要花时间(越来越多)
- 明明内存足够,却无法申请空间(剩余空间不是连续的)
2.2 链表Linked-list
#ifndef _NODE_H_
#define _NODE_H_
typedef struct _node {
int value;
struct _node *next;
} Node;
#endif
2.3 链表的函数
实例:读入一些数(不知道有多少个)并记录下来,读到-1为止。
#include"node.h"
#include<stdio.h>
#include<stdlib.h>
typedef struct _list {
Node* head;
//Node* tail; //可以改进代码
} List;
void add(List* pList, int number);
void print(List *plist);
int main()
{
List list;
int number;
list.head = NULL;
do {
scanf("%d", &number);
if (number != -1) {
head = add(&list, number);
}
} while (number != -1);
print(&list); //遍历输出
/*****链表的搜索*****/
scanf("%d", &number);
Node *p;
int isFound = 0;
for ( p=list.head; p; p=p->next) {
if ( p->value == number ) {
printf("找到了\n");
isFound = 1;
break;
}
}
if ( !isFound ) {
printf("没找到\n");
}
return 0;
}
void add(List* pList, int number)
{
//添加元素至链表
Node *p = (Node*)malloc(sizeof(Node));
p->value = number;
p->next = NULL;
//找到最后一个表
Node *last = pList->head;
if ( last ) {
while ( last->next ) {
last = last->next;
}
//将表链接起来
last->next = p;
} else {
pList->head = p; //boundary situation
}
}
void print(List *pList)
{
Node *p;
/*链表的遍历*/
for ( p=pList.head; p; p=p->next) {
printf("%d\t", p->value);
}
printf("\n");
}
2.4 链表的搜索
链表的遍历:
void print(List *pList)
{
Node *p;
/*链表的遍历*/
for ( p=pList.head; p; p=p->next) {
printf("%d\t", p->value);
}
printf("\n");
}
链表的搜索:
scanf("%d", &number);
Node *p;
int isFound = 0;
for ( p=list.head; p; p=p->next) {
if ( p->value == number ) {
printf("找到了\n");
isFound = 1;
break;
}
}
if ( !isFound ) {
printf("没找到\n");
}
2.5 链表的删除
Node *q;
for ( q=NULL, p=list.head; p; q=p, p=p->next) {
if ( p->value == number) {
if(q) {
q->next = p->next;
} else {
list.head = p->next; //boundary situation
}
free(p);
break;
}
}
使用指针
时如何寻找边界条件?
当指针出现在->next
左边时,需要判断该指针是不是NULL,以保证安全
2.6 链表的清除
for ( p=head; p; p=q) {
q = p->next;
free(p);
}