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, elem_type 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 elem_type get_data(seq_list *slt, int position) {
   2     return slt->elem[position-1];

3.7. 顺序表任意位置插入

   1 void insert(seq_list *slt, int position, elem_type x) { 
   2     int i;
   3     position--;
   4     for(i = slt->size; i > position; i--) 
   5         slt->elem[i] = slt->elem[i-1];
   6     slt->elem[position]=x;
   7     slt->size++;
   8 }

插入算法时间性能分析

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

void remove(seq_list *slt, int position) {
    int i;
    position--;
    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 remove(node *pre) 
   2 {
   3    node *p = pre->next;
   4    pre->next=p->next;
   5    free(p);
   6 }

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

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

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

   1 void remove_x(node *head, elem_type x) 
   2 {
   3    node *pre = head;
   4    while(pre->next!= NULL && 
   5       pre->next->data != x) 
   6    {
   7       pre=pre->next;
   8    }
   9    remove(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, elem_type x) 
   2 {
   3    head = head->next;
   4    while(head!=NULL && head->data != x) 
   5    {
   6       head=head->next;
   7    }
   8    return head;
   9 }

4.8. 思考

如何实现:

5. 不带头结点的单链表

6. 循环单链表

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

6.2. 循环单链表插入

6.3. 循环单链表的删除

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

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

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

7. 双链表

7.1. 双链表存储结构

   1 struct double_node{
   2    elem_type data;
   3    double_node *next;   
   4 };
   5 typedef struct double_node double_node;
   6 typedef struct double_node *double_list;

7.2. 双链表的插入

7.3. 双链表的删除

8. 练习

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