程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 數據結構實驗 單鏈表

數據結構實驗 單鏈表

編輯:C++入門知識

編寫一個完整的程序,實現單鏈表的建立、插入、刪除、輸出等基本操作。

(1)建立一個帶頭結點的單鏈表。

(2)計算單鏈表的長度,然後輸出單鏈表。

(3)查找值為x的直接前驅結點q。

(4)刪除值為x的結點。

(5)把單向鏈表中元素逆置(不允許申請新的結點空間)。

(6)已知單鏈表中元素遞增有序,請寫出一個高效的算法,刪除表中所有值大於mink且小於maxk的元素(若表中存在這樣的元素),同時釋放被刪結點空間,並分析你的算法的時間復雜度(注意:mink和maxk是給定的兩個參變量,他們的值可以和表中的元素相同,也可以不同)。

(7)同(6)的條件,試寫一高效的算法,刪除表中所有值相同的多余元素(使得操作後的線性表中所有元素的值均不相同),同時釋放被刪結點空間,並分析你的算法時間復雜度。

(8)利用(1)建立的鏈表,實現將其分解成兩個鏈表,其中一個全部為奇數,另一個全部為偶數(盡量利用已知的存儲空間)。

(9)在主函數中設計一個簡單的菜單,分別測試上述算法。


[cpp]
//因為沒有要求輸入的鏈表數據的數量,所以我用-1表示輸入結束。  
//測試數據 1 2 3 4 5 6 -1  
//測試刪除相同元素的數據 2 2 3 3 4 4 5 5  
#include<stdio.h>  
#include<stdlib.h>  
struct node 

    int data; 
    node *next; 
}; 
node *h,*h1,*h2; 
void Creatlist()//創建鏈表  

    node *s,*e; 
    h=(node *)malloc(sizeof(node)); 
    s=(node *)malloc(sizeof(node)); 
    h->next=s; 
    printf("請輸入單鏈表數據:     "); 
    scanf("%d",&s->data); 
    e=h; 
    while(s->data!=-1)//用-1表示鏈表輸入終止  
    { 
        e=s; 
        s=(node *)malloc(sizeof(node)); 
        scanf("%d",&s->data); 
        e->next=s; 
    } 
    e->next=NULL; 
    return ; 

void Printlist(node *h)//輸出鏈表  

    int count; 
    node *s; 
    s=h; 
    count=0; 
    while(s->next!=NULL)//先遍歷一遍,用count記錄鏈表的長度。  
    { 
        count++; 
        s=s->next; 
    } 
    printf("單鏈表長度:           %d\n",count); 
    if(count==0) 
    { 
        printf("鏈表為空!\n"); 
        return ; 
    } 
    printf("單鏈表數據:           "); 
    s=h; 
    while(s->next!=NULL) 
    { 
        s=s->next; 
        printf("%d ",s->data);    
    } 
    printf("\n"); 
    return ; 

void Findlist()//查找值為x的前驅結點  

    int x; 
    node *s,*e; 
    printf("請輸入待查找的數值:   "); 
    scanf("%d",&x); 
    s=h->next; 
    if(s->data==x) 
    { 
        printf("%d沒有前驅結點!\n",x);//x為第一個結點  
        return ; 
    } 
    e=s->next; 
    while(e->data!=x&&e->next!=NULL) 
    { 
        s=e; 
        e=s->next; 
    } 
    if(e->data!=x) 
    { 
        printf("單鏈表中不存在值為%d的結點!\n",x);//鏈表中沒有x  
        return ; 
    } 
    printf("%d的前驅結點為:        %d\n",x,s->data); 
    return ; 

void Deletlist()//刪除值為x的結點,實驗中沒有要求,我寫的時候是按鏈表中只有一個值為x的結點。  

    int x; 
    node *s,*e; 
    printf("請輸入需要刪除的數值: "); 
    scanf("%d",&x); 
    s=h; 
    e=s->next; 
    while(e->data!=x&&e->next!=NULL) 
    { 
        s=e; 
        e=s->next; 
    } 
    if(e->data!=x) 
    { 
        printf("單鏈表中不存在值為%d的結點!\n",x);//鏈表中沒有值為x的結點  
        return ; 
    } 
    s->next=e->next; 
    free(e); 
    return ; 

void Inverlist()//逆置鏈表,將連接鏈表的指針方向倒轉,不需要申請新的空間。  

    node *s,*e,*r; 
    s=h->next; 
    e=s->next; 
    if(e==NULL) 
    { 
        h->next=s; 
        return ; 
    } 
    s->next=NULL; 
    r=e->next; 
    while(e!=NULL) 
    { 
        e->next=s; 
        s=e; 
        e=r; 
        if(e==NULL) 
            break; 
        r=e->next; 
    } 
    h->next=s; 
    return ; 

void Delexylist()//刪除鏈表中x和y之間的數字,而且要求釋放內存。既然要求釋放內存,那就只能遍歷,我沒想到什麼更高效的算法,因為鏈表是有序的,我釋放到值為y結束。  

    int x,y; 
    node *s,*e,*r; 
    printf("請輸入需要刪除的區間   "); 
    scanf("%d %d",&x,&y); 
    r=h; 
    s=h->next; 
    while(s->data<=y&&s->next!=NULL) 
    { 
        e=s->next; 
        if(s->data>=x) 
        { 
            free(s); 
            r->next=e; 
        } 
        else 
            r=s; 
        s=e; 
    } 
    return ; 

void DeleSamelist()//刪除相同元素的結點同時釋放內存空間。同樣需要遍歷,沒有想到特別高效的算法。  

    int temp; 
    node *s,*e,*r; 
    r=h; 
    s=h->next; 
    if(s==NULL) 
        return ; 
    temp=-1; 
    while(s!=NULL) 
    { 
        e=s->next; 
        if(s->data==temp) 
        { 
            free(s); 
            r->next=e; 
        } 
        else 
        { 
            temp=s->data; 
            r=s; 
        } 
        s=e;     
    } 
    return ; 

void Cutlist()//分拆鏈表。  

    node *s,*s1,*e1,*s2,*e2; 
    h1=(node *)malloc(sizeof(node)); 
    s1=(node *)malloc(sizeof(node)); 
    h2=(node *)malloc(sizeof(node)); 
    s2=(node *)malloc(sizeof(node)); 
    e1=h1; 
    e1->next=NULL; 
    e2=h2; 
    e2->next=NULL; 
    s=h->next; 
    while(s!=NULL) 
    { 
        if(s->data%2!=0) 
        { 
            s1->data=s->data; 
            e1->next=s1; 
            e1=s1; 
            e1->next=NULL; 
            s1=(node *)malloc(sizeof(node)); 
        } 
        else 
        { 
            s2->data=s->data; 
            e2->next=s2; 
            e2=s2; 
            e2->next=NULL; 
            s2=(node *)malloc(sizeof(node)); 
        } 
        s=s->next;//第一次寫的時候沒有加上這一句,電腦直接就卡死了。。。。  
    } 
    Printlist(h1); 
    Printlist(h2); 
    return ; 

int Opra() 

    int T; 
    printf("*****************目錄******************\n"); 
    printf("創建一個單鏈表:                      1\n"); 
    printf("計算單鏈表長度並輸出單鏈表:          2\n"); 
    printf("查找值為x的前驅結點:                 3\n"); 
    printf("刪除值為x的結點:                     4\n"); 
    printf("把單鏈表中的元素逆置:                5\n"); 
    printf("刪除單鏈表中值在x和y之間的元素:      6\n"); 
    printf("刪除鏈表中值相同的元素:              7\n"); 
    printf("將鏈表分成兩部分:                    8\n"); 
    printf("操作結束:                            0\n"); 
    printf("輸入操作代號:         "); 
    scanf("%d",&T); 
    switch(T) 
    { 
        case 1:Creatlist();break; 
        case 2:Printlist(h);break; 
        case 3:Findlist(); break; 
        case 4:Deletlist();break; 
        case 5:Inverlist();break; 
        case 6:Delexylist();break; 
        case 7:DeleSamelist();break; 
        case 8:Cutlist();break; 
        case 0:return 0; 
        default :printf("輸入錯誤,請重新輸入!\n");break; 
    } 
    return 1; 

int main() 

    int flag=1; 
    while(1) 
    { 
        flag=Opra(); 
        if(!flag)//用flag控制是否跳出循環。  
            break; 
        printf("\n\n"); 
    } 
    printf("謝謝使用!\n"); 
    return 0; 
}    

//因為沒有要求輸入的鏈表數據的數量,所以我用-1表示輸入結束。
//測試數據 1 2 3 4 5 6 -1
//測試刪除相同元素的數據 2 2 3 3 4 4 5 5
#include<stdio.h>
#include<stdlib.h>
struct node
{
 int data;
 node *next;
};
node *h,*h1,*h2;
void Creatlist()//創建鏈表
{
 node *s,*e;
 h=(node *)malloc(sizeof(node));
 s=(node *)malloc(sizeof(node));
 h->next=s;
 printf("請輸入單鏈表數據:     ");
 scanf("%d",&s->data);
 e=h;
 while(s->data!=-1)//用-1表示鏈表輸入終止
 {
  e=s;
  s=(node *)malloc(sizeof(node));
  scanf("%d",&s->data);
  e->next=s;
 }
 e->next=NULL;
 return ;
}
void Printlist(node *h)//輸出鏈表
{
 int count;
 node *s;
 s=h;
 count=0;
 while(s->next!=NULL)//先遍歷一遍,用count記錄鏈表的長度。
 {
  count++;
  s=s->next;
 }
 printf("單鏈表長度:           %d\n",count);
 if(count==0)
 {
  printf("鏈表為空!\n");
  return ;
 }
 printf("單鏈表數據:           ");
 s=h;
 while(s->next!=NULL)
 {
  s=s->next;
  printf("%d ",s->data); 
 }
 printf("\n");
 return ;
}
void Findlist()//查找值為x的前驅結點
{
 int x;
 node *s,*e;
 printf("請輸入待查找的數值:   ");
 scanf("%d",&x);
 s=h->next;
 if(s->data==x)
 {
  printf("%d沒有前驅結點!\n",x);//x為第一個結點
  return ;
 }
 e=s->next;
 while(e->data!=x&&e->next!=NULL)
 {
  s=e;
  e=s->next;
 }
 if(e->data!=x)
 {
  printf("單鏈表中不存在值為%d的結點!\n",x);//鏈表中沒有x
  return ;
 }
 printf("%d的前驅結點為:        %d\n",x,s->data);
 return ;
}
void Deletlist()//刪除值為x的結點,實驗中沒有要求,我寫的時候是按鏈表中只有一個值為x的結點。
{
 int x;
 node *s,*e;
 printf("請輸入需要刪除的數值: ");
 scanf("%d",&x);
 s=h;
 e=s->next;
 while(e->data!=x&&e->next!=NULL)
 {
  s=e;
  e=s->next;
 }
 if(e->data!=x)
 {
  printf("單鏈表中不存在值為%d的結點!\n",x);//鏈表中沒有值為x的結點
  return ;
 }
 s->next=e->next;
 free(e);
 return ;
}
void Inverlist()//逆置鏈表,將連接鏈表的指針方向倒轉,不需要申請新的空間。
{
 node *s,*e,*r;
 s=h->next;
 e=s->next;
 if(e==NULL)
 {
  h->next=s;
  return ;
 }
 s->next=NULL;
 r=e->next;
 while(e!=NULL)
 {
  e->next=s;
  s=e;
  e=r;
  if(e==NULL)
   break;
  r=e->next;
 }
 h->next=s;
 return ;
}
void Delexylist()//刪除鏈表中x和y之間的數字,而且要求釋放內存。既然要求釋放內存,那就只能遍歷,我沒想到什麼更高效的算法,因為鏈表是有序的,我釋放到值為y結束。
{
 int x,y;
 node *s,*e,*r;
 printf("請輸入需要刪除的區間   ");
 scanf("%d %d",&x,&y);
 r=h;
 s=h->next;
 while(s->data<=y&&s->next!=NULL)
 {
  e=s->next;
  if(s->data>=x)
  {
   free(s);
   r->next=e;
  }
  else
   r=s;
  s=e;
 }
 return ;
}
void DeleSamelist()//刪除相同元素的結點同時釋放內存空間。同樣需要遍歷,沒有想到特別高效的算法。
{
 int temp;
 node *s,*e,*r;
 r=h;
 s=h->next;
 if(s==NULL)
  return ;
 temp=-1;
 while(s!=NULL)
 {
  e=s->next;
  if(s->data==temp)
  {
   free(s);
   r->next=e;
  }
  else
  {
   temp=s->data;
   r=s;
  }
  s=e; 
 }
 return ;
}
void Cutlist()//分拆鏈表。
{
 node *s,*s1,*e1,*s2,*e2;
 h1=(node *)malloc(sizeof(node));
 s1=(node *)malloc(sizeof(node));
 h2=(node *)malloc(sizeof(node));
 s2=(node *)malloc(sizeof(node));
 e1=h1;
 e1->next=NULL;
 e2=h2;
 e2->next=NULL;
 s=h->next;
 while(s!=NULL)
 {
  if(s->data%2!=0)
  {
   s1->data=s->data;
   e1->next=s1;
   e1=s1;
   e1->next=NULL;
   s1=(node *)malloc(sizeof(node));
  }
  else
  {
   s2->data=s->data;
   e2->next=s2;
   e2=s2;
   e2->next=NULL;
   s2=(node *)malloc(sizeof(node));
  }
  s=s->next;//第一次寫的時候沒有加上這一句,電腦直接就卡死了。。。。
 }
 Printlist(h1);
 Printlist(h2);
 return ;
}
int Opra()
{
 int T;
 printf("*****************目錄******************\n");
 printf("創建一個單鏈表:                      1\n");
 printf("計算單鏈表長度並輸出單鏈表:          2\n");
 printf("查找值為x的前驅結點:                 3\n");
 printf("刪除值為x的結點:                     4\n");
 printf("把單鏈表中的元素逆置:                5\n");
 printf("刪除單鏈表中值在x和y之間的元素:      6\n");
 printf("刪除鏈表中值相同的元素:              7\n");
 printf("將鏈表分成兩部分:                    8\n");
 printf("操作結束:                            0\n");
 printf("輸入操作代號:         ");
 scanf("%d",&T);
 switch(T)
 {
  case 1:Creatlist();break;
  case 2:Printlist(h);break;
  case 3:Findlist(); break;
  case 4:Deletlist();break;
  case 5:Inverlist();break;
  case 6:Delexylist();break;
  case 7:DeleSamelist();break;
  case 8:Cutlist();break;
  case 0:return 0;
  default :printf("輸入錯誤,請重新輸入!\n");break;
 }
 return 1;
}
int main()
{
 int flag=1;
 while(1)
 {
  flag=Opra();
  if(!flag)//用flag控制是否跳出循環。
   break;
  printf("\n\n");
 }
 printf("謝謝使用!\n");
 return 0;

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved