[C语言]进阶|链表

---------------------------------------------------------------------------------------

可变数组:

array.h

#ifndef _ARRAY_H_
#define _ARRAY_H_

typedef struct {
    int *array;
    int size;
} Array;

// Array不定义成指针类型 *Array 的原因:定义成变量使用范围更广,如果定义一个指针类型,那么 array p 其实不容易看出是指针 // 函数原型 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_set(Array *a, int index, int value); int array_get(const Array *a, int index); void array_inflate(Array *a, int more_size); #endif

 

//  main.c
//  Created by weichen on 15/7/7.
//  Copyright (c) 2015年 weichen. All rights reserved.

#include "array.h"
#include <stdio.h>
#include <stdlib.h>

const int BLOCK_SIZE = 20;

Array array_create(int init_size)
{
    Array a;
    a.size = init_size;
    a.array = (int*)malloc(sizeof(int) * a.size);
    return a;   // 返回变量本身
}

void array_free(Array *a)
{
    free(a->array);
    a->array = NULL;
    a->size = 0;
}

// 封装
int array_size(const Array *a)
{
    return a->size;
}

// 返回指针
int* array_at(Array *a, int index)
{
    if ( index >= a->size) {
        // index位于哪个block,加1后乘以block,得到下一个block,最后减去原来的size
        array_inflate(a, (index/BLOCK_SIZE+1)*BLOCK_SIZE - a->size);
    }
    return &(a->array[index]);
}

void array_set(Array *a, int index, int value)
{
    a->array[index] = value;
}

int array_get(const Array *a, int index)
{
    return a->array[index];
}

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; a++) {
        p[i] = a->array[i];
    }
    // 释放内存空间
    free(a->array);
    // 赋值到a
    a->array = p;
    a->size += more_size;
}

int main(int argc, const char * argv[]) {
    /*
     可变数组(Resizable Array)
     
     Think about a set of functions that provide a mechanism of resizable array of int.
     Growable (可变大)
     Get the current size (当前的大小)
     Access to the elements  (可访问单元)
     
     the Interface
     Array array_create(int int_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); //让数组长大
     
     array.h
     
     #ifndef _ARRAY_H_
     #define _ARRAY_H_
     
     typeof struct {
     int *array;
     int size;
     } Array;       // Array 不定义成指针类型 *Array 的原因:定义成变量使用范围更广,如果定义一个指针类型,那么 array p 其实不容易看出是指针
     
     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
     
     */
    
    
    Array a = array_create(100);
    //printf("%d\n", a.size);
    //printf("%d\n", array_size(&a)); // 如果版本升级,直接用a.size不容易更改,封装保护具体实现细节
    
    //*array_at(&a, 0) = 10;  //函数调用返回指针,加*号指向指针所指的东西,变量可以赋值
    //printf("%d\n", *array_at(&a, 0));
    
    //上面写法的转换
    array_set(&a, 0, 10);
    array_set(&a, 1, 14);
    printf("%d\n", array_get(&a, 0));   //10
    
    // 可变数组自动增长
    int number = 0;
    int cnt = 0;
    while(number != -1) {
        scanf("%d", &number);   // 随便输入数字,循环输出数组a的值,-1停止
        if(number != -1) {
            number = *array_at(&a, cnt++);
            printf("%d\n", number);
        }
    }
    
    array_free(&a);
    
    return 0;
}

 

链表操作:

node.h

#ifndef _NODE_H_
#define _NODE_H_

typedef struct _node {
    int value;          // 数据
    struct _node *next; // 指针,下一个指向它自己(不能写成 Node *next,因为在这之后才定义的Node)
} Node;                 // 定义Node类型

#endif

 

//  main.c
// Created by weichen on 15/7/8. // Copyright (c) 2015年 weichen. All rights reserved. #include "node.h" #include <stdio.h> #include <stdlib.h> //typedef struct _node { // int value; // struct _node *next; //} Node; int main(int argc, const char * argv[]) { /* 链表 可变数组的缺陷: 拷贝需要花时间,如果原数组很大,会很慢 由于新数组需要申请更大的空间,由于之前还没free掉,总有一个时间点会出现尽管总内存够但无法再申请足够使用的情况 所以可变数组不够高效 解决办法: linked blocks,no copy 就只申请block那么大的内存,与原来的内存空间链起来 理想中的效果: |-------------| | 内存1 |---+ |-------------| | +--------------------+ | |-------------| +->| block |---+ |-------------| | +--------------------+ | |-------------| +->| block | |-------------| 实际中: head | |-------------| |--------------| |-------------| | 数据 | point |--->| 数据 | point |--->| 数据 | point | |-------------| |--------------| |---------|---| - 整个结构叫做链表,其中带有数据的叫做结点 让last一开始等于第一个的数据,看next有没有东西,让last所指那个东西的下一个,于是last指向了第二个的数据 */ Node *head = NULL; int number; do { scanf("%d\n", &number); if ( number != -1 ) { // add to linked-list Node *p = (Node*)malloc(sizeof(Node)); // 为结构分配一块内存空间 p->value = number; // 初始化值为number p->next = NULL; // 初始化第一个的next为null,即下一个为null // find the last Node *last = head; // 初始化:最后一个就是当前的这个 if ( last ) { // 如果last不为null了 while ( last->next ) { // 如果最后一个还有next的话,last就是last的next last = last->next; // 当循环停止时,last所指的就是最后一个 } // attach last->next = p; } else { head = p; // 只有第一个,head为p } } } while ( number != -1 ); return 0; }

  改进:

//  main.c

#include "node.h"
#include <stdio.h>
#include <stdlib.h>

// 单独定义一个数据类型表示list
typedef struct _list {
    Node* head;
} List;

void add(List* list, int number);

int main(int argc, const char * argv[]) {
   
    List list;
    int number;
    list.head = NULL;
    
    do {
        scanf("%d\n", &number);
        
        if (number != -1) {
       add(&list, number);
} } while(number != -1); 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; } }

 

搜索

删除

清除

 

Link:http://www.cnblogs.com/farwish/p/4628952.html

posted on 2015-07-13 01:20  ercom  阅读(606)  评论(0编辑  收藏  举报