2014-12-27 41 views
0

我需要編寫一個返回鏈表大小的函數。這似乎很簡單,但是當我嘗試推進我的指針時,我得到了一個異常。 這是代碼:在鏈表中拋出異常

int List_size(List *list) 
{ 
    List_node *p; 
    int counter = 0; 
    p = list->head; 

    while (p != NULL) 
    { 
     p = p->next; 
     counter = counter + 1; 
    } 
    return counter; 
} 

這是定義鏈表代碼:

​​

這是創建列表的代碼:

List *create_list(int n) 
{ 
    List *list = (List*) calloc(n,sizeof(List)); 
    list->head = NULL; 
    return list; 
} 

最後,我已經使用這兩個函數將數據(數字)插入到列表中:(所以不要認爲列表是空的)。

void insert_first(List_node *x, List *list) 
{ 
    x->next = list->head; 
    list->head = x; 
} 

void insert(List_node *x, List_node *y) 
{ 
    x->next = y->next; 
    y->next = x; 
} 

List_node *mk_node(int data, int n) 
{ 
    List_node *node = (List_node *)calloc(n, sizeof(List_node)); 
    node->data = data; 
    return node; 
} 

使用斷點我發現問題出在p = p-> next,但我不明白爲什麼。

非常感謝。

編輯 - 我沒想到的全部代碼是必要的,但在這裏它是:

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h> 
#include <stdlib.h> 
#include "List.h" 

void merge(List *small_list, List *big_list) 
{ 
    List_node *x, *y; 
    y = small_list->head; 
    x = big_list->head; 
    t = x->prev; 

// while (y < x) //If there are smaller numbers on the small list, insert them first 
// { 
//  insert(y,t) 
//  t = t->next; 
//  y = y->next; 
// } 

    while (y != NULL && x->next != NULL) 
    { 
     if (x <= y && x->next >= y) 
     { 
      insert(y, x); 
      y = y->next; 
     } 
     else 
      x = x->next; 
    } 
    while (y != NULL) 
    { 
     insert(y, x); 
     y = y->next; 
    } 
} 

void main() 
{ 
    List *L1, *L2, *big_list, *small_list; 
    int num1, num2; 
    int i; 
    int a, b; 

    create_list(5,&L1); 
    create_list(3,&L2); 

    printf("Insert first number into L1\n"); 
    scanf("%d", &num1); 
    node = mk_node(0,5); 
    insert_first(node, &L1); 
    for (i = 0; i<5; i++) 
    { 
     printf("Now insert the rest of the numbers\n"); 
     scanf("%d", &num1); 
     next = mk_node(&num1,5); 
     insert(next, node); 
     node = next; 
    } 

    printf("Insert first number into L2\n"); 
    scanf("%d", &num2); 
    node = mk_node(0,3); 
    insert_first(node, &L2); 
    for (i = 0; i<3; i++) 
    { 
     printf("Now insert the rest of the numbers\n"); 
     scanf("%d", &num2); 
     next = mk_node(&num2,3); 
     insert(next, node); 
     node = next; 
    } 

//If lists are in descending order, reverse them to ascending order 
     //if (L1->head > L1->head->next) 
    //  reverse(L1); 
    // if (L2->head > L2->head->next) 
     // reverse(L2); 

    int size_L1 = List_size(L1); 
    int size_L2 = List_size(L2); 

    if (size_L1 <= size_L2) 
    { 
     big_list = L2; 
     small_list = L1; 
    } 
    else 
    { 
     big_list = L1; 
     small_list = L2; 
    } 

    merge(small_list, big_list); 

    print_list(L3); 
    getchar(); getchar(); 
} 

正如你所看到的,我使用插入功能插入()的數字。我希望它是好的。

功能相反的是:(我真的希望它的作品,我把它翻譯從僞代碼)

List reverse(List *list) 
{ 
    List_node *x, *y, *z; 
    if (list->head == NULL || list->head->next == NULL) 
    { 
     return *list; 
    } 
    x = list->head; 
    y = list->head->next; 
    z = list->head->next->next; 
    x->next = NULL; 
    while (z != NULL) 
    { 
     y->next = x; 
     x = y; 
     y = z; 
     z = z->next; 
    } 
    y->next = x; 
    list->head = y; 
} 

基本上,這是說,我有一個分配兩個2定向分類鏈表,我應該把它們合併成一個大的排序鏈表。

至於例外情況 - Lists.exe中0x00E21766處未處理的異常:0xC0000005:訪問衝突讀取位置0xCCCCCCD0。

編輯 - 在print_list功能:

void print_list(List *list) 
{ 
    List_node *p; 
    p = list->head; 
    printf("The linked list consists of: "); 
    while (p != NULL) 
    { 
     printf("%d ", p->data); 
     p = p->next; 
    } 
    printf("\n"); 
} 
+3

似乎你沒有設置'x-> next = NULL',因爲它需要設置爲NULL,以便列表在某個點結束。看看[LinkedListBasics](http://cslibrary.stanford.edu/103/LinkedListBasics.pdf)以供參考。 – Abhinav 2014-12-27 14:56:23

+1

你究竟是如何在列表中插入值的? – 2014-12-27 15:04:08

+1

「異常」 - 如果您指出哪一個可能會有所幫助。 – usr2564301 2014-12-27 16:01:13

回答

1

我添加上面評論我複製你的代碼到我的編譯器,它不能編譯,所以它不會運行:以create_list調用不編譯:有返回值函數返回,不在一個參數中;有未申報的變數。此外,給create_list和mk_node一個參數是沒有用的:它們將分配一個數組,而不是創建一個列表元素。 calloc(1,sizeof(your_thing))的調用就足夠了。固定這些erors後,幾個錯誤變得明顯:

  • 在insert_first(節點,& L2);你給它的列表地址,這已經是一個指針。刪除'&'(編譯器應該抱怨!)。
  • 相同爲List_size(& L1); L1已經是一個指針。刪除'&'。
  • 在:如果(X < = Y ...)你比較的內存地址。更改爲:如果(X->數據< = Y->數據...)
  • 該聲明的一部分「X->下一個> = Y」也比較內存地址,我不明白爲什麼它是需要。我刪除它。

真正的問題似乎是在合併。您應該將列表合併到L1中,或者合併到L2中,最好應創建一個結果列表。但是你「隨機」插入一個元素到L1中,然後到L2中,然後再次插入到L1等中。在我的測試中,它無限期地運行。以下合併工作正常:

List *merge(List *small_list, List *big_list) 
{ 
    List_node *x, *y, *r; 
    List *result= create_list(); 
    y = small_list->head; 
    x = big_list->head; 

    if (x->data < y->data) 
     {result->head= x; x= x->next;} 
    else {result->head= y; y= y->next;} 
    r= result->head; 

    while (y != NULL && x != NULL) 
    { 
     if (x->data < y->data) 
     { 
      r->next= x; 
      x = x->next; 
     } 
     else { 
      r->next= y; 
      y = y->next; 
     } 
     r= r->next; 
    } 
    while (y != NULL) 
    { 
     r->next= y; 
     y = y->next; 
     r= r->next; 
    } 
    while (x != NULL) 
    { 
     r->next= x; 
     x = x->next; 
     r= r->next; 
    } 
    r->next= 0; 
    return (result); 
} 
+0

好吧,所以我查看了你的筆記並使用了你的功能,但現在我想打印清單,而且我似乎無法做到。我打印的數字是奇怪的數字(內存地址?)。我發佈了一個名爲'print_list'的函數,你可以看看它嗎?謝謝。 – Eran 2015-01-02 19:07:02

+0

沒關係,我找到了問題。只是想再次表示感謝,現在一切正常。 – Eran 2015-01-03 15:43:04

3

的問題是在代碼中你並沒有顯示,因爲所有你給的代碼是罰款(*)。

我可以用你的結構和功能:

  • 創建一個列表
  • 添加第一個節點(與insert_first)
  • 添加其他節點(與插入)
  • 獲得大小(使用List_size)
  • 顯示每個節點的數據值
  • 釋放節點和列表

下面是完整的代碼:

#include <stdio.h> 
#include <malloc.h> 

typedef struct List_node 
{ 
    int data; 
    struct List_node *next; 
    struct List_node *prev; 
}List_node; 

typedef struct List 
{ 
    List_node *head; 
}List; 

List *create_list() 
{ 
    List *list = (List*) malloc(sizeof(List)); 
    list->head = NULL; 
    return list; 
} 

int List_size(List *list) 
{ 
    List_node *p; 
    int counter = 0; 
    p = list->head; 

    while (p != NULL) 
    { 
     p = p->next; 
     counter = counter + 1; 
    } 
    return counter; 
} 

void insert_first(List_node *x, List *list) 
{ 
    x->next = list->head; 
    list->head = x; 
} 

void insert(List_node *x, List_node *y) 
{ 
    x->next = y->next; 
    y->next = x; 
} 

/* my own additions */ 
List_node *mk_node(int data) { 
    List_node *node = (List_node *) malloc(sizeof(List_node)); 
    node->data = data; 
    return node; 
} 

void delete_list(List *list) { 
    List_node *node = list->head; 
    while (node != NULL) { 
     List_node *next = node ->next; 
     free(node); 
     node = next; 
    } 
    free(list); 
} 

int main() { 
    List* list = create_list(); 
    List_node *node, *next; 
    int i; 

    node = mk_node(0); 
    insert_first(node, list); 
    for (i=1; i<5; i++) { 
     next = mk_node(i); 
     insert(next, node); 
     node = next; 
    } 

    int n = List_size(list); 
    printf("size : %d\n", n); 

    node = list->head; 
    while (node != NULL) { 
     printf("node val : %d\n", node->data); 
     node = node->next; 
    } 
    delete_list(list); 
    return 0; 
} 

(*)你的代碼是不完美的,因爲List_node結構包含一個指向prev是從來沒有使用過,所以你用每三值單鏈表結束沒用過。

+0

* prev *稍後會用到(我沒有將它包含在代碼中,但我會)。 – Eran 2014-12-27 17:05:57

+0

@Eran我認爲這是類似的東西...所以你的代碼很好,你顯示什麼! – 2014-12-27 18:35:31

+0

只需確保 - 在0(到節點)和4(到下一個)之間的數字之後插入* node *和* next *?我假設你給了* node *數字0,所以稍後它會被覆蓋,並且* next *我應該給出我從用戶那裏得到的數字? – Eran 2014-12-27 20:02:31

1

所以,問題是你分配表頭,但從來沒有在列表中的元素分配內存。嗶嘰增加了mk_node它的分配(所以嗶嘰解決了它)。

+0

好吧,循環有點工作,但是當計數器達到5(這是列表的大小)時拋出另一個異常:'在Lists.exe中的0x003817F0處出現未處理的異常:0xC0000005:訪問衝突讀取位置0xCCCCCCD0.'我試着改變while循環內部到while(p-> next!= NULL),但它給了我同樣的錯誤。 – Eran 2014-12-28 08:38:35

+0

使用calloc代替malloc。 calloc清零內存; malloc不。所以如果你測試爲零,你不會看到零,因爲內存還沒有被歸零。值0xCCCCetc是調試模式下編譯器的典型特徵,它有意將內存設置爲此值,以便您的程序獲取此錯誤,以便您知道您忘記將其清零。 (我使用MS VC 2005,它是這樣做的) – 2014-12-28 16:06:56

+0

p.s .:你能發佈你的修正代碼嗎? – 2014-12-28 16:08:17