連結串列操作源程式 (轉)

worldblog發表於2007-12-13
連結串列操作源程式 (轉)[@more@]

  連結串列,是資料結構的基礎。利用連結串列,我們可以很好的實現資料的管理。但是我們經常在網上看見各式各樣的有關連結串列的問題,在此我給出了一個比較簡單但是功能比較強大的來給大家顯示關於連結串列的。如果你很深入的瞭解了下面程式的工作原理,說明你對連結串列的理解就算過關了,如果不能,請仔細閱讀一下下面的程式,特別注意程式指標的修改順序。 特別是連結串列的倒置程式,不超過10行就搞定了,還沒有額外的申請空間,何樂而不為? 程式在VC6下編譯透過

#include :namespace prefix = o ns = "urn:schemas--com::office" />

#include

#include

#include

 

/* 書中的常量定義 */

#define OK  1

#define ERROR  0

#define OVERFLOW (-1)

 

typedef int Status;

 

/* 定義了一個學生的結構體 */

typedef struct {

  int sn;   /* 學號 */

  char name[32]; /* 姓名 */

  int re;  /* 成績 */

} data_t;

 

/* 定義了連結串列的節點形式為一個單連結串列 */

typedef struct LNODE {

  data_t data;

  struct LNODE * next;

}node_t, *link_t;

 

/* 建立一個有頭節點的連結串列 */

link_t create_link();

 

/* 銷燬連結串列,釋放節點空間 */

void  destroy_link(link_t head);

 

/* 在連結串列的第 idx 位置插入一個節點,節點的值由 d 給出*/

/* 注意 idx 為插入節點後的位置,且從0開始計算 */

Status insert_node(link_t head, int idx, data_t e);

 

/* 刪除連結串列的第 idx 個節點,並將刪除的內容填入e所指向的空間*/

/* idx也是從0開始計算 */

Status delete_node(link_t head, int idx, data_t* e);

 

 

/* 判斷連結串列是否為空 */

Status empty_link(link_t head);

 

/* 獲得連結串列的長度 */

int  length_link(link_t head);

 

/* 獲得連結串列的第i個元素的位置,並返回該元素的指標,NULL表示無效 */

node_t* locate_link(link_t head, int idx);

 

/* 列印連結串列的內容 */

void print_link(link_t head);

 

/* 將一個連結串列倒置 */

void reverse_link(link_t head);

 

/* 鍵盤命令對映表 */

const char *help[] =

{

  "?,h,H  -- this helpn",

  "a,A,i,I -- add a node, ex: a 10n",

  "d,D  -- del a node, ex: d 10n",

  "p,P  -- print this linkn",

  "g,G  -- get link numn",

  "r,R  -- reverse the linkn",

  "x,X,q,Q -- exit this programn",

};

 

/* 程式入口 */

int main(int argc, char* argv[])

{

  char cmd;

  int i, idx;

  data_t tmp;

 

  link_t head = create_link();

  for (i=0; i<10; i++)  { /*預先插入10個節點*/

  tmp.sn = i; tmp.score = 100-i; strcpy(tmp.name, "ttttt");

    insert_node(head, i, tmp);

  }

  print_link(head);

  printf("input command: ");

  while ( cmd = getch())

  {

    printf("%cn", cmd);

  switch (cmd)

  {

  case '?': case 'h':  case 'H': /*列印幫助資訊*/

    for (i=0; i<sizeof(help)/sizeof(help[0]); i++)

    printf("t%s", help[i]);

    printf("n");

    break;

  case 'a': case 'A':  case 'i': case 'I': /*插入一個節點*/

    printf("please input where do you want to insert: ");

    scanf("%d", &idx);

  if (idx < 0 || idx > length_link(head))  {

    printf("insert perror!n");

    break;

  }

    printf("please input the SN, name and score:");

    scanf("%d%s%d", &tmp.sn, tmp.name, &tmp.score);

  if (insert_node(head, idx, tmp) == ERROR){

    printf("insert error!n");

    break;

  }

    printf("insert OK!n");

    print_link(head);

    break;

  case 'd': case 'D': /*刪除一個節點*/

    printf("please input which do you want to delete: ");

    scanf("%d", &idx);

  if (idx < 0 || idx >= length_link(head))  {

    printf("delete pos error!n");

    break;

  }

  if (delete_node(head, idx, &tmp) == NULL) {

    printf("input error!n");

    break;

  }

    printf("delete OKn");

    print_link(head);

    break;

  case 'p': case 'P': /* 列印連結串列*/

    print_link(head);

    break;

 

  case 'x': case 'X':  case 'q':  case 'Q':/*退出程式*/

    destroy_link(head);

    return 0;

  case 'r': case 'R': /*倒置連結串列*/

    reverse_link(head);

    printf("this link have been reversed!n");

    print_link(head);

    break;

    default:

    printf("input error!, for help, please input ?n");

  }

    printf("nninput command: ");

  }

 

  return 0;

}

 

link_t create_link()

{

  link_t head;

  head = (link_t)malloc(sizeof(node_t));

  head->next = NULL;

  head->data.sn = 0;

  return head;

}

 

void  destroy_link(link_t head)

{

  node_t *p = head;

  while (head != NULL) {

  p = head->next;

  free (head);

  head = p;

  }

}

void  print_link(link_t head)

{

  node_t *p = head->next; /*跳過頭節點*/

  int cnt = 0;

  printf("pos :  SN %20s scoren", "name  ");

  while (p != NULL) {

    printf("%04d: %4d%20s%4dn",

cnt++, p->data.sn, p->data.name, p->data.score);

  p = p->next;

  }

}

 

Status  empty_link(link_t head)

{

  if (head==NULL || head->next == NULL)

  return OK;

  else

  return ERROR;

}

 

int  length_link(link_t head)

{

  int len = 0;

  node_t *p = head->next;

  for(; p!=NULL; p = p->next)

len++;

  return len;

}

 

node_t* locate_link(link_t head, int idx)

{

  int pos = -1;

  node_t *p = head;

  while (p!=NULL && pos < idx) {

  p = p->next; pos ++;

  }

  return p;

}

 

 

Status insert_node(link_t head, int idx, data_t e)

{

  node_t *add = NULL; /* 待加入的節點指標 */

  node_t *p = locate_link(head, idx-1); /*注意查詢idx-1*/

  if (p == NULL) return ERROR;

 

  add = (node_t *)malloc(sizeof(node_t));

  add->data = e;

  add->next = p->next;

  p->next = add;

  return OK;

}

 

Status delete_node(link_t head, int idx, data_t *e)

{

  node_t *p = locate_link(head, idx-1); /*注意查詢idx-1*/

  node_t *q = NULL; /* p為待刪除的節點指標 */

  if (p == NULL || p->next== NULL) return ERROR;

  q = p->next;

 

  *e = q->data;

  p->next = q->next;

  free (q);

  return OK;

}

 

void reverse_link(link_t head)

{

  node_t *p1, *p2;

  p1 = head->next;

  head->next = NULL;

 

  while (p1 != NULL)  {

  p2 = p1->next;

    p1->next = head->next;

    head->next = p1;

  p1 = p2;

  }

}

 

  大家看見了,上面的每一個子都很簡單,不超過10行。唯一的只有main函式比較長。而main函式卻實現了一個常用的選單操作的示例,包括幫助、連結串列的插入、刪除等功能的命令與功能實現的對應,也是各個函式功能組合為各種具體功能的實現。

 

 ——小兒科,大家別扔磚頭,雞蛋可以!


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992971/,如需轉載,請註明出處,否則將追究法律責任。

相關文章