zoukankan      html  css  js  c++  java
  • 《算法导论》第十章----基本数据结构

    《算法导论》学习记录目录

    基本的数据结构是很基础的东西,而且运行时间也很容易看出来,所以本文也是简单地提及一些性质,主要还是通过一些练习来熟悉它们的性质。

    (PS:无聊翻开TAOCP的第一卷,发现第二章也是讲一些数据结构,而且讲得很详细。如果明年年初计划可以完成,就应该开始看TAOCP,继续努力吧!)

    栈是先进后出(后进先出),就好像洗盘子的时候,你最先放的盘子在最底,下次拿出来洗,就是最后才拿出来。(例子举得有点搓。。。)

    具体操作为进栈、出栈(也叫压入、弹出)。

    因为是基于数组来实现栈,所以不仅仅要注意下溢(空栈出栈),还要注意上溢(满栈进栈)。

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 #define MAX 6
     5 
     6 typedef struct {
     7     int array[MAX];
     8     int top;
     9 }Stack;                             //栈结构体,包含数组和栈顶下标的记录。
    10 
    11 int stack_empty(Stack *S);          //判断是否为空栈
    12 
    13 void push(Stack *S, int x);         //进栈操作
    14 
    15 int pop(Stack *S);                  //出栈操作
    16 
    17 int main(){
    18     Stack *S;
    19     S->top = -1;
    20     //stack_empty(S);
    21     pop(S);
    22     int i, num;
    23     for(i = 0; i <= 5; i++){
    24         scanf("%d", &num);
    25         push(S, num);
    26     }
    27 
    28     int p = pop(S);
    29     printf("%d
    ", p);
    30 
    31     return 0;
    32 }
    33 
    34 /*
    35  * 栈顶初始为-1,判断是否为-1
    36  */
    37 int stack_empty(Stack *S){
    38     if(S->top == -1)
    39         return 1;
    40     else
    41         return 0;
    42 }
    43 
    44 /*
    45  * 进栈操作,如果栈顶的下标刚好为数组的结尾,就提示上溢,不能再进栈
    46  */
    47 void push(Stack *S, int x){
    48     if(S->top+1 == MAX){
    49         printf("overflow
    ");
    50         return ;
    51     }
    52     else{
    53         S->top++;
    54         S->array[S->top] = x;
    55     }
    56 }
    57 
    58 /*
    59  * 出栈操作,如果栈为空,提示下溢,不能出栈
    60  */
    61 int pop(Stack *S){
    62     if(stack_empty(S)){
    63         printf("underflow
    ");
    64         return ;
    65     }
    66     else{
    67         //S->top--;
    68         return S->array[S->top--];
    69     }
    70 }
    View Code

    练习10.1-2

    说明如何用一个数组A[1..n]来实现两个栈,使得两个栈中的元素总数不到n时,两者都不会发生上溢。注意PUSH和POP操作的时间应为O(1)

    分别将数组的头和尾作为单独的两个栈。见代码。

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 #define MAX 12
     5 
     6 typedef struct {
     7     int array[MAX];
     8     int top_1;
     9     int top_2;
    10     //int which;
    11 }T_Stack;                                   //栈结构,一个数组,两个栈顶下标(一头一尾)
    12 
    13 int empty(T_Stack *T_S, int which);         //判断栈是否为空,which为1对应数组头的那个栈,which为2对应数组尾的那个栈
    14 
    15 void push(T_Stack *T_S, int which, int x);  //进栈操作
    16 
    17 int pop(T_Stack *T_S, int which);           //出栈操作
    18 
    19 int main(){
    20     int i, num;
    21     T_Stack *T_S;
    22     T_S->top_1 = -1;
    23     T_S->top_2 = MAX;
    24     
    25     for(i = 1; i <= 6; i++){
    26         scanf("%d", &num);
    27         push(T_S, 1, num);
    28     }
    29 
    30     for(i = 1; i <= 6; i++){
    31         scanf("%d", &num);
    32         push(T_S, 2, num);
    33     }
    34 
    35     int po = pop(T_S, 1);
    36     printf("%d
    ", po);
    37 
    38     po = pop(T_S, 2);
    39     printf("%d
    ", po);
    40 
    41 
    42     return 0;
    43 }
    44 
    45 int empty(T_Stack *T_S, int which){
    46     if(which == 1){
    47         if(T_S->top_1 == -1)
    48             return 1;
    49         else
    50             return 0;
    51     }
    52 
    53     else if(which == 2){
    54         if(T_S->top_2 == MAX)
    55             return 1;
    56         else
    57             return 0;
    58     }
    59 }
    60 
    61 void push(T_Stack *T_S, int which, int x){
    62     if(T_S->top_1 + 1 == T_S->top_2){
    63         printf("overflow
    ");
    64         return ;
    65     }
    66 
    67     if(which == 1){
    68         T_S->top_1++;
    69         T_S->array[T_S->top_1] = x;
    70     }
    71     else if(which == 2){
    72         T_S->top_2--;
    73         T_S->array[T_S->top_2] = x;
    74     }
    75 }
    76 
    77 int pop(T_Stack *T_S, int which){
    78     if(which == 1){
    79         if(empty(T_S, which)){
    80             printf("underflow
    ");
    81             return ;
    82         }
    83         else{
    84             //T_S->top1--;
    85             return T_S->array[T_S->top_1--];
    86         }
    87     }
    88     else if(which == 2){
    89         if(empty(T_S, which)){
    90             printf("underflow
    ");
    91             return ;
    92         }
    93         else{
    94             //T_S->top2++;
    95             return T_S->array[T_S->top_2++];
    96         }
    97     }
    98 }
    View Code

    队列

    队列是先进先出,就和排队一样,排头的比排尾的先。

    具体操作为入队、出队。

    同样是因为基于数组来实现(循环数组),所以要注意下溢(队列为空,再出队)和上溢(队列为满,再入队)。(PS:代码已添加处理上下溢问题,练习10.1-4)

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 #define MAX 7
     5 
     6 typedef struct {
     7     int array[MAX];
     8     int head;
     9     int tail;
    10 }Queue;                             //队列结构体,一个数组,一个队首下标,一个队尾下标
    11 
    12 void enqueue(Queue *Q, int x);      //进队列
    13 
    14 int dequeue(Queue *Q);              //出队列
    15 
    16 int main(){
    17     int i, num;
    18     Queue *Q;
    19     Q->head = Q->tail = 0;
    20     dequeue(Q);
    21     for(i = 1; i <= 6; i++){
    22         scanf("%d", &num);
    23         enqueue(Q, num);
    24     }
    25 
    26     for(i = 1; i <= 6; i++){
    27         int de = dequeue(Q);
    28         printf("%d
    ", de);
    29     }
    30     if(Q->head == Q->tail)
    31         printf("Yes
    ");
    32     return 0;
    33 }
    34 
    35 /*
    36  * 如果队首下标等于队尾下标+1,表示上溢,不能再进队列。
    37  * 如果队尾下标在添加元素后等于数组的末端,那么就要回到数组的前端(前提未上溢)
    38  */
    39 void enqueue(Queue *Q, int x){
    40     if(Q->head == ((Q->tail + 1) % MAX)){
    41         printf("overflow
    ");
    42         return ;
    43     }
    44 
    45     else{
    46         Q->array[Q->tail] = x;
    47         Q->tail = (Q->tail + 1) % MAX;
    48     }
    49 }
    50 
    51 /*
    52  * 如果队首下标等于队尾下标,表示队列为空,不能出队列
    53  * 如果队首小表在出队列后等于数组末端,那么就要回到数组的前端
    54  */
    55 int dequeue(Queue *Q){
    56     if(Q->head == Q->tail){
    57         printf("underflow
    ");
    58         return ;
    59     }
    60     int x = Q->array[Q->head];
    61     if(Q->head == MAX-1)
    62         Q->head = 0;
    63     else
    64         Q->head++;
    65 
    66     return x;
    67 }
    View Code

    练习10.1-5

    栈的插入和删除都在同一端进行,而队列的插入和删除却在两头进行。另有一种双端队列,其两端都可以左插入和删除操作。对于一个用数组构造的双端队列,请写出四个在两端进行插入和删除操作的过程,要求运行时间都为O(1)

    PS:已添加处理上下溢问题

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 #define MAX 15
     5 
     6 typedef struct {
     7     int array[MAX];
     8     int head;
     9     int tail;
    10 }Deque;                             //双端队列结构体,一个数组、一个头下标、一个尾下标
    11 
    12 void H_enqueue(Deque *D, int x);    //从队列头进队列
    13 
    14 int H_dequeue(Deque *D);            //从队列头出队列
    15 
    16 void T_enqueue(Deque *D, int x);    //从队列尾进队列
    17 
    18 int T_dequeue(Deque *D);            //从队列尾出队列
    19 
    20 int main(){
    21     int i, num;
    22     Deque *de;
    23     de->head = de->tail = 0;
    24     H_dequeue(de);
    25     T_dequeue(de);
    26     for(i = 1; i <= 7; i++){
    27         scanf("%d", &num);
    28         H_enqueue(de, num);
    29     }
    30     for(i = 1; i <= 7; i++){
    31         scanf("%d", &num);
    32         T_enqueue(de, num);
    33     }
    34     int H_de = H_dequeue(de);
    35     int T_de = T_dequeue(de);
    36     printf("%d
    ", H_de);
    37     printf("%d
    ", T_de);
    38 
    39     return 0;
    40 }
    41 
    42 void H_enqueue(Deque *D, int x){
    43     if(D->head == ((D->tail + 1) % MAX)){
    44         printf("overflow
    ");
    45         return ;
    46     }
    47 
    48     else{
    49         if(D->head == 0)
    50             D->head = MAX-1;  
    51         else
    52             D->head--;
    53         D->array[D->head] = x;
    54     }
    55 }
    56 
    57 int H_dequeue(Deque *D){
    58     if(D->head == D->tail){
    59         printf("underflow
    ");
    60         return ;
    61     }
    62     int x = D->array[D->head];
    63     if(D->head == MAX-1)
    64         D->head = 0;
    65     else
    66         D->head++;
    67 
    68     return x;
    69 }
    70 
    71 void T_enqueue(Deque *D, int x){
    72     if(D->head == ((D->tail + 1) % MAX)){
    73         printf("overflow
    ");
    74         return ;
    75     }
    76 
    77     else{
    78         D->array[D->tail] = x;
    79         D->tail = (D->tail + 1) % MAX;
    80     }
    81 }
    82 
    83 int T_dequeue(Deque *D){
    84     if(D->head == D->tail){
    85         printf("underflow
    ");
    86         return ;
    87     }
    88 
    89     int x = D->array[D->tail-1];
    90     if(D->tail == 0)
    91         D->tail = MAX-1;
    92     else
    93         D->tail--;
    94     
    95     return x;
    96 }
    View Code

    练习10.1-6

    说明如何用两个栈实现一个队列,并分析有关队列操作的运行时间

    一个栈为A、一个栈为B。入队列的时候相当于进B栈,如果B栈已经为满栈的时候,将B栈的所有元素出栈,再进A栈,然后把要入队列的元素进B栈。如果A、B栈同为满栈的时候,为上溢。出队列时就从A栈弹出(如果A栈为空,先从B栈依次弹出并一次进A栈)。PS:代码可能有瑕疵。。。。

    #include <stdio.h>
    
    #define MAX 4
    
    typedef struct {
        int array[MAX];
        int top;
    }Stack;
    
    typedef struct {
        Stack pr_stack;
        Stack ne_stack;
    }Queue;
    
    int stack_empty(Stack *S);
    
    int push(Stack *S, int x);
    
    int pop(Stack *S);
    
    void enqueue(Queue *Q, int x);
    
    int dequeue(Queue *Q);
    
    int main(){
        int i, num;
        Queue *Q;
        Stack Sp;
        Sp.top = -1;
        Stack Sn;
        Sn.top = -1;
        Q->pr_stack = Sp;
        Q->ne_stack = Sn;
        
        dequeue(Q);
        for(i = 1; i <= 8; i++){
            scanf("%d", &num);
            enqueue(Q, num);
        }
        enqueue(Q, num+1);
    
        int de;
        for(i = 1; i <= 8; i++){
            de = dequeue(Q);
            printf("%d ", de);
        }
        printf("
    ");
        return 0;
    }
    
    int stack_empty(Stack *S){
        if(S->top == -1)
            return 1;
        else
            return 0;
    }
    
    int push(Stack *S, int x){
        if(S->top+1 == MAX){
            return 0;
        }
        else{
            S->top++;
            S->array[S->top] = x;
            return 1;
        }
    }
    
    int pop(Stack *S){
        if(stack_empty(S)){
            printf("underflow
    ");
            return ;
        }
        else{
            return S->array[S->top--];
        }
    }
    
    void enqueue(Queue *Q, int x){
        if(push(&Q->ne_stack, x) == 0){
            if(Q->pr_stack.top+1 == MAX){
                printf("overflow
    ");
                return ;
            }
            else{
                while(Q->pr_stack.top+1 != MAX && !(stack_empty(&Q->ne_stack))){
                    push(&Q->pr_stack, pop(&Q->ne_stack));
                }
                push(&Q->ne_stack, x);
            }
        }
    }
    
    int dequeue(Queue *Q){
        if(stack_empty(&Q->pr_stack)){
            if(stack_empty(&Q->ne_stack)){
                printf("underflow
    ");
                return ;
            }
    
            while(Q->pr_stack.top+1 != MAX && !(stack_empty(&Q->ne_stack))){
                push(&Q->pr_stack, pop(&Q->ne_stack));
            }
        }
        return pop(&Q->pr_stack);
    }
    View Code

    链表

    链表中的对象按照线性顺序排序,不像数组通过下标来决定对象的线性序,链表的顺序是由对象的指针来决定的。

    PS:下列为单链表实现代码(头插入),注意要释放删除结点的内存。

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 typedef struct ListNode{
     5     int value;
     6     struct ListNode * next;
     7 }ListNode;                          //链表结点结构体,对象的值,后指针
     8 
     9 void list_insert(ListNode *l , int x);  //链表的插入,头插入
    10 
    11 void print_list(ListNode *l);           //打印链表
    12 
    13 int list_search(ListNode *l, int k);    //链表的查找,k为要查找的值
    14 
    15 void list_delete(ListNode *l, int k);   //链表的删除,k为要删除的结点的值
    16 
    17 int main(){
    18     ListNode *head;                         //头节点
    19     int i, num;
    20     head = (ListNode *)malloc(sizeof(ListNode));
    21     head->next = NULL;
    22 
    23     for(i = 1; i <= 5; i++){
    24         scanf("%d", &num);
    25         list_insert(head, num);
    26     }
    27 
    28     print_list(head);
    29 
    30     printf("%d
    ", list_search(head, 3));
    31 
    32     list_delete(head, 5);
    33     print_list(head);
    34     return 0;
    35 }
    36 
    37 void list_insert(ListNode *l, int x){
    38     ListNode * p;
    39     p = (ListNode *)malloc(sizeof(ListNode));
    40     p->value = x;
    41     if(l->next == NULL){
    42         l->next = p;
    43         p->next = NULL;
    44     }
    45     else{
    46         p->next = l->next;
    47         l->next = p;
    48     }
    49     
    50 }
    51 
    52 void print_list(ListNode *l){
    53     ListNode * p = l->next;
    54     while(p != NULL){
    55         printf("%d ", p->value);
    56         p = p->next;
    57     }
    58     printf("
    ");
    59 }
    60 
    61 int list_search(ListNode *l, int key){
    62     ListNode *p = l->next;
    63     while(p != NULL){
    64         if(p->value == key)
    65             return 1;
    66         p = p->next;
    67     }
    68 
    69     return 0;
    70 }
    71 
    72 void list_delete(ListNode *l, int key){
    73     ListNode *p = l->next;
    74 
    75     if(p->value == key){
    76         l->next = p->next;
    77         free(p);
    78     }
    79     else{
    80         while(p->next->value != key){
    81             p = p->next;
    82         }
    83         ListNode *de = p->next;
    84         p->next = p->next->next;
    85         free(de);               //要释放删除节点的内存
    86     }
    87 }
    View Code

    PS:下列为双链表代码实现(头插入)。(注释参考单链表。。。)(添加日期:2013.10.27)

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 typedef struct ListNode {
     5     int value;
     6     struct ListNode * next;
     7     struct ListNode * prev;
     8 }ListNode;
     9 
    10 void list_insert(ListNode *l, int x);
    11 
    12 void print_list(ListNode *l);
    13 
    14 int list_search(ListNode *l, int k);
    15 
    16 void list_delete(ListNode *l, int k);
    17 
    18 int main(){
    19     int i, num;
    20     ListNode *head;
    21     head = (ListNode *)malloc(sizeof(ListNode));
    22     head->next = NULL;
    23 
    24     for(i = 1; i <= 5; i++){
    25         scanf("%d", &num);
    26         list_insert(head, num);
    27     }
    28     //print_list(head);
    29     list_delete(head, 3);
    30     print_list(head);
    31     return 0;
    32 }
    33 
    34 void list_insert(ListNode *l, int x){
    35     ListNode * n;
    36     n = (ListNode *)malloc(sizeof(ListNode));
    37     n->value = x;
    38 
    39     if(l->next == NULL){
    40         l->next = n;
    41         n->prev = l;
    42         n->next = NULL;
    43     }
    44 
    45     else{
    46         n->next = l->next;
    47         l->next->prev = n;
    48         l->next = n;
    49         n->prev = l;
    50     }
    51 }
    52 
    53 void print_list(ListNode *l){
    54     ListNode *p = l->next;
    55 
    56     while(p != NULL){
    57         printf("%d ", p->value);
    58         p = p->next;
    59     }
    60 
    61     printf("
    ");
    62 }
    63 
    64 int list_search(ListNode *l, int k){
    65     ListNode *p = l->next;
    66 
    67     while(p != NULL){
    68         if(p->value == k){
    69             return 1;
    70         }
    71         p = p->next;
    72     }
    73 
    74     return 0;
    75 }
    76 
    77 void list_delete(ListNode *l, int k){
    78     ListNode *p = l->next;
    79     while(p != NULL){
    80         if(p->value == k){
    81             p->prev->next = p->next;
    82             p->next->prev = p->prev;
    83 
    84             free(p);
    85         }
    86         p = p->next;
    87     }
    88 }
    View Code

    练习10.2-2

    用一单链表L实现一个栈,要求PUSH和POP操作的时间仍为O(1)

    该单链表的插入为头插入,对应PUSH操作,POP操作为删除头结点指向的下一结点。

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 typedef struct ListNode{
     5     int value;
     6     struct ListNode * next;
     7 }ListNode;
     8 
     9 typedef struct {
    10     ListNode * top;
    11 }Stack;
    12 
    13 void list_insert(ListNode *l , int x);
    14 
    15 void print_list(ListNode *l);
    16 
    17 int stack_empty(Stack *S);
    18 
    19 void push(Stack *S, int x);
    20 
    21 int pop(Stack *S);
    22 
    23 int main(){
    24     int i, num;
    25     Stack * S;
    26     S = (Stack *)malloc(sizeof(Stack));
    27     S->top = (ListNode *)malloc(sizeof(ListNode));
    28 
    29     for(i = 1; i <= 5; i++){
    30         scanf("%d", &num);
    31         push(S, num);
    32     }
    33 
    34     //printf("%d
    ", stack_empty(S));
    35     //print_list(S->top);
    36 
    37     for(i = 1; i<= 5; i++)
    38         printf("%d ", pop(S));
    39     printf("
    ");
    40 
    41     return 0;
    42 }
    43 
    44 void list_insert(ListNode *l, int x){
    45     ListNode * p;
    46     p = (ListNode *)malloc(sizeof(ListNode));
    47     p->value = x;
    48     if(l->next == NULL){
    49         l->next = p;
    50         p->next = NULL;
    51     }
    52     else{
    53         p->next = l->next;
    54     }
    55     l->next = p;
    56 }
    57 
    58 void print_list(ListNode *l){
    59     ListNode * p = l->next;
    60     while(p != NULL){
    61         printf("%d ", p->value);
    62         p = p->next;
    63     }
    64     printf("
    ");
    65 }
    66 
    67 
    68 int stack_empty(Stack *S){
    69     if(S->top->next == NULL)
    70         return 1;
    71     else
    72         return 0;
    73 }
    74 
    75 void push(Stack *S, int x){
    76     list_insert(S->top, x);
    77 }
    78 
    79 int pop(Stack *S){
    80     if(stack_empty(S)){
    81         printf("underflow
    ");
    82         return ;
    83     }
    84     else{
    85         ListNode *p = S->top->next;
    86         int x = p->value;
    87         S->top->next = p->next;
    88         free(p);
    89         return x;
    90     }
    91 }
    View Code

    PS:还有一些练习没完成。。完成会不定期更新。。。。

    还要继续努力,朝着目标进发!!!

  • 相关阅读:
    J2EE中常用的名词解释
    java中的构造方法
    String s = new String("xyz");创建了几个StringObject?
    MySQL 学习笔记
    《SQL 必知必会》建表语句
    《SQL 必知必会》读书笔记
    IDEA 中项目代码修改后不自动生效,需要执行 mvn clean install 才生效
    curl 使用指南
    MySQL字段添加注释,但不改变字段的类型
    《痞子衡嵌入式半月刊》 第 14 期
  • 原文地址:https://www.cnblogs.com/alan-forever/p/3378647.html
Copyright © 2011-2022 走看看