第2章 線性表 - 單鏈表順序存儲結構
——《數據結構》-嚴蔚敏.吳偉民版
概述
數據結構的學習當然要從線性表學起,而線性表裏首先需要學習單鏈表,這裏從單鏈表最簡單的順序存儲結構(本質就是可變數組存儲)開始。
解析
單鏈表強調元素在邏輯上緊密相鄰,所以首先想到用數組存儲。但是普通數組有着無法克服的容量限制,在不知道輸入有多少的情況下,很難確定出一個合適的容量。對此,一個較好的解決方案就是使用動態數組。首先用malloc申請一塊擁有指定初始容量的內存,這塊內存用作存儲單鏈表元素,當錄入的內容不斷增加,以至於超出了初始容量時,就用calloc擴展內存容量,這樣就做到了既不浪費內存,又可以讓單鏈表容量隨輸入的增加而自適應大小。
單鏈表順序存儲結構如下圖:
可能涉及到的語法難點
剛接觸數據結構的同學,單鏈表順序存儲結構可能會是其面對的第一個坎。這裏涉及到了結構體、動態數組、結構指針,甚至還有函數變量(函數做參數,本質是函數指針),所以需要有相對紮實的語言語法基礎。當然,這也並不是說一定得掌握了高級語法才能開始學習數據結構,可以先將語言學到入門(入門意味着學會了提問),再邊學數據結構邊鞏固語法。一定要親自動手寫一寫,否則,肯定學不好。
概述
數據結構的學習當然要從線性表學起,而線性表裏首先需要學習單鏈表,這裏從單鏈表最簡單的順序存儲結構(本質就是可變數組存儲)開始。
解析
單鏈表強調元素在邏輯上緊密相鄰,所以首先想到用數組存儲。但是普通數組有着無法克服的容量限制,在不知道輸入有多少的情況下,很難確定出一個合適的容量。對此,一個較好的解決方案就是使用動態數組。首先用malloc申請一塊擁有指定初始容量的內存,這塊內存用作存儲單鏈表元素,當錄入的內容不斷增加,以至於超出了初始容量時,就用calloc擴展內存容量,這樣就做到了既不浪費內存,又可以讓單鏈表容量隨輸入的增加而自適應大小。
單鏈表順序存儲結構如下圖:
可能涉及到的語法難點
剛接觸數據結構的同學,單鏈表順序存儲結構可能會是其面對的第一個坎。這裏涉及到了結構體、動態數組、結構指針,甚至還有函數變量(函數做參數,本質是函數指針),所以需要有相對紮實的語言語法基礎。當然,這也並不是說一定得掌握了高級語法才能開始學習數據結構,可以先將語言學到入門(入門意味着學會了提問),再邊學數據結構邊鞏固語法。一定要親自動手寫一寫,否則,肯定學不好。
stdlib 是c標準庫 typedef 是起名字
#include"stdio.h"#include"stdlib.h"
#define TRUE 1
#define ERROR 0
typedef struct
{
int * elem; //儲存空間基地址
int length; // 記錄當前鏈表長度
int listsize; //鏈表規模
} SqList;
int InitList(SqList *L)
{
(*L).elem =(int*)malloc( 100*sizeof(int) ); //返回NULL
if (!(*L).elem)
{
printf("順序表初始化失敗");
exit(-2); //內存分配失敗
}
(*L).length=1;
(*L).listsize =100;
return 1;
}
void Clear_Sq(SqList *L)
{
(*L).length =0;
}
void Destroy(SqList*L)
{
free((*L).elem);
(*L).elem =NULL;
(*L).length =0;
}
int ListEmpty_Sq(SqList L) //值拷貝
{
return L.length ==0 ?1:0;
}
int ListLength_Sq(SqList L)
{
return L.length ;
}
int GetEle_Sq(SqList L,int i,int *e)
{
if (i<1||i>L.length)
return 0;
*e =L.elem[i-1];
return 1;
}
/*
往順序表中插入值。數字下標從零開始。
*/
int ListInsert_Sq(SqList *L ,int i, int e)
{
int * newbase;
int *p,*q;
if (i<1||i>(*L).length)
return 0;
if((*L).length >=(*L).listsize)
{
newbase = ( int *)realloc ((*L).elem,((*L).listsize+10)*sizeof(int));
// 第一個參數是線性表節點地址 第二個參數是在開闢多大的內存 。
(*L) .elem = newbase;
(*L).listsize+=10;
}
q =&(*L).elem[i-1];
for (p=&(*L).elem[(*L).length-1];p>=q;--p) //元素儲存位置挨個減一 ,插入第一個數不進入這個循環。
{
*(p+1)=*p;
}
*q=e;
(*L).length++;
return 1;
}
int LocateElem_Sq(SqList L,int e )
{
int i=1;
while(i<L.length && L.elem [i-1]!=e)
{
i++;
}
if (i<L.length )
{ return i;
}
return 0;
}
int ListDelete_Sq(SqList *L,int i,int *e)
{
int j;
int *p,*q ;
if (i<1||i>(*L).length )
return 0;
p=&(*L).elem [i-1];
*e=*p;
q=(*L).elem +(*L).length -1;//elem[length-1]
for (++p;p<=q;++p)
{
*(p-1)= *p;
}
(*L).length--;
return 1;
}
/* 線性表遍歷 從0到legnth-1;
*/
int ListTraverse_Sq(SqList L)
{
int i;
for (i=0;i<L.length-1 ;i++)
printf(" 打表 %d ",L.elem [i]);
}
int main()
{
SqList L;
int e;
int i;
if(InitList(&L)==1)
{
printf("順序表初始化成功\n");
}
printf("當前線性表長度%d\n",L.length-1);
// L.length=1;
//ListTraverse_Sq(L);
for(i=1;i<10;i++)
ListInsert_Sq(&L,i, 2*i); //插入一個元素
printf("當前線性表長度%d\n",L.length-1);
printf("4的定 =% d\n",LocateElem_Sq(L,4));
ListTraverse_Sq(L);
ListDelete_Sq(&L,2,&e);
printf("刪除的第二個元素是%d\n",e);
ListTraverse_Sq(L);
return 0;
}
用插入一個值給鏈表複製時候如果,鏈表長度小於1,會出現ele[-1],這個錯誤。
概述
數據結構的學習當然要從線性表學起,而線性表裏首先需要學習單鏈表,這裏從單鏈表最簡單的順序存儲結構(本質就是可變數組存儲)開始。
解析
單鏈表強調元素在邏輯上緊密相鄰,所以首先想到用數組存儲。但是普通數組有着無法克服的容量限制,在不知道輸入有多少的情況下,很難確定出一個合適的容量。對此,一個較好的解決方案就是使用動態數組。首先用malloc申請一塊擁有指定初始容量的內存,這塊內存用作存儲單鏈表元素,當錄入的內容不斷增加,以至於超出了初始容量時,就用calloc擴展內存容量,這樣就做到了既不浪費內存,又可以讓單鏈表容量隨輸入的增加而自適應大小。
單鏈表順序存儲結構如下圖:
可能涉及到的語法難點
剛接觸數據結構的同學,單鏈表順序存儲結構可能會是其面對的第一個坎。這裏涉及到了結構體、動態數組、結構指針,甚至還有函數變量(函數做參數,本質是函數指針),所以需要有相對紮實的語言語法基礎。當然,這也並不是說一定得掌握了高級語法才能開始學習數據結構,可以先將語言學到入門(入門意味着學會了提問),再邊學數據結構邊鞏固語法。一定要親自動手寫一寫,否則,肯定學不好。