TableOfContents

线性表Linear List

1. 线性表逻辑结构

2. 线性表的基本运算

对于实际问题中涉及的其它更为复杂的运算,可以用基本运算的组合来实现。

3. 线性表的顺序存储(顺序表 Sequential List)

3.1. 顺序表的存储结构

   1 #define MAXSIZE 100
   2 typedef int elem_type;
   3 typedef struct{
   4     elem_type  elem[MAXSIZE];
   5     int size; //表示数组中元素个数
   6 }seq_list;

3.2. 初始化

   1 void init( seq_list * slt) {
   2     slt->size=0;
   3 }

3.3. 顺序表的遍历

   1 void print(seq_list  *slt)
   2 {
   3    int i;
   4    for( i=0; i < slt->size; i++) 
   5         printf("%5d", slt->elem[i]);
   6 }

3.4. 判断顺序表是否为空

   1 int is_empty( seq_list  *slt ) {
   2      return  slt->size==0;
   3 }

3.5. 查找顺序表中值为x的结点位置

   1 int locate(seq_list *slt, ElemType x)
   2 {
   3     int i=0;
   4     while(i < slt->size && slt->elem[i]!=x) 
   5         i++;
   6     return i<=slt->last? i+1:-1;
   7 }

3.6. 取得顺序表中第i个结点的值

   1 ElemType get_data(seq_list *slt, int position) {
   2     position--;
   3     if(position < 0 || position >= slt->size){
   4         ElemType x;
   5         printf("invalid position!");
   6         return x;
   7     } else
   8         return slt->elem[position];
   9 }

3.7. 顺序表任意位置插入

   1 void insert(seq_list *slt, int position, ElemType x) { 
   2     int i;
   3     position--;
   4     if(slt->size == MAXSIZE){ 
   5         printf("Full"); return;
   6     }
   7     if(position < 0 || position > slt->size) {
   8         printf("invalid position!"); return;
   9     }
  10     for(i = slt->size; i > position; i--) 
  11         slt->elem[i] = slt->elem[i-1];
  12     slt->elem[position]=x;
  13     slt->size++;
  14 }

插入算法时间性能分析

3.8. 删除顺序表中任意元素

void delete_list(seq_list *slt, int position) {
    int i;
    position--;
    if(slt->size==0) {
        printf("empty");return;
    }
    if(position<0 || position >= slt->size) {
        printf("invalid position!");return;
    }
    for(i=position; i<slt->size-1; i++) 
        slt->elem[i]=slt->elem[i+1];
    slt->size--;
}

删除算法时间效率

3.9. 顺序表的用法举例

int main() {
    seq_list  sqlist;
    init_list(&sqlist);
    insert_list(&sqlist, 1, 1);
    print_list(&sqlist);
    printf("%d", locate_list(&sqlist, 10));
    printf("%d", locate_list(&sqlist, 11));
    while(!empty_list(&sqlist))
        delete_list(&sqlist, sqlist.size);
    print_list(&sqlist);
}

4. 线性表的链式存储(带头结点的单链表)

4.1. 链表的存储结构

   1 typedef int elem_type;
   2 struct node{
   3    elem_type data;
   4    struct node *next;
   5 };
   6 typedef struct node node;
   7 typedef struct node *link_list; 

4.2. 初始化

   1 void init(link_list *list) {
   2    *list = (link_list)malloc(sizeof(node));
   3    (*list)->next = NULL;
   4 }

4.3. 插入算法

   1 void insert(node *q, elem_type x) 
   2 {
   3    p = (node*)malloc(sizeof(node));
   4    p->data = x;
   5    p->next = q->next;
   6    q->next = p;
   7 }

4.4. 插入特定位置

   1 void insert_pos(link_list node, int pos, elem_type x) 
   2 {
   3    while(pos > 1) {
   4         node = node->next;
   5         pos--;
   6    }
   7    insert(node, x);
   8 }

4.5. 删除算法

   1 void delete(Node *pre) 
   2 {
   3    Node *p = pre->next;
   4    pre->next=p->next;
   5    free(p);
   6 }

4.6. 删除特定位置元素算法

   1 void delete_pos(Node *node, int pos) 
   2 {
   3    while(pos > 1) {
   4       node = node->next;
   5       pos--;
   6    }
   7    delete(head);
   8 }

=== 删除特定值的元素算法 ==

   1 void delete_list_x(Node *head, ElemType x) 
   2 {
   3    node *pre = head;
   4    while(pre->next!= NULL && 
   5       pre->next->data != x) 
   6    {
   7       pre=pre->next;
   8    }
   9    delete_list(pre);
  10 }

4.7. 查找算法

   1 Node *get_data(Node *head, int pos) 
   2 {
   3    while(pos > 0) {
   4       head = head->next;
   5       pos--;
   6    }
   7    return head;
   8 }

   1 Node *find_x(Node *head, ElemType x) 
   2 {
   3    head = head->next;
   4    while(head!=NULL && 
   5       head->data != x) 
   6    {
   7       head=head->next;
   8    }
   9    return head;
  10 }

5. 思考

如何实现:

不带头结点的单链表

不设开始的头结点,head指针直接指向第一个元素。

插入、删除操作比较繁琐

循环单链表

如果希望从表中的任意一个结点开始,都能访问到表中的所有其它结点,可以设置表中最后一个结点的指针域指向表中的第一个结点,这种链表称为循环单链表(或单循环链表)

1. 循环单链表与单链表的不同

2. 循环单链表插入

3. 循环单链表的删除

4. 只设尾指针的循环单链表

在循环单链表中,常常只设一个尾指针不设头指针。

5. 例子:合并两个循环单链表

练习

  1. 设计一个算法,求顺序表中值为x的元素的个数。
  2. 设计一个算法,将顺序表倒置。
  3. 已知一个顺序表中的各结点的值是从小到大有序的,设计一个算法,插入一个值为x的结点,使顺序表中的结点仍然是从小到大有序的。
ch3n2k.com | Copyright (c) 2004-2020 czk.