資料結構中單鏈表的實現+單鏈表的C語言實現原始碼
阿新 • • 發佈:2019-02-18
線性表(List):零個或多個數據元素的有限序列。線性表的抽象資料型別。
線性表的順序儲存:
優點:無須為表示表中元素的邏輯關係而額外的儲存空間,可以快速的取表中任意位置的元素。
缺點:插入和刪除操作需要轉移大量元素,線性表的長度較大時,難以確定儲存空間的容量, 造成儲存空間的“碎片”。
線性表的鏈式儲存:
為了表示每一個數據元素a1與其直接後級資料元素ai+1之間的邏輯關係,對資料元素a1來說,除了儲存其本身的資訊之外,還需儲存一個指示其直接後繼的訊號(即直接後繼的儲存位置)。儲存資料元素資訊的域叫做資料域,把儲存直接後繼位置的域稱為指標域。指標域中儲存的資訊稱為指標或鏈。這兩部分組成資料元素ai
其中頭指標和頭結點的區別:
1,頭指標是指向連結串列的第一個結點的指標,若連結串列有都結點,則指向頭結點的指標。頭指標具有標示作用,所以常用頭指標冠以連結串列的名字。無論連結串列是否為空,頭指標均不為空,頭指標是連結串列的必要條件。
2,頭結點是為了操作的統一和方便設定的,放在頭一個元素的結點之前,其資料域一般無意義。有了頭結點,對其在第一元素位置前插入刪除擦偶偶與其他結點的操作統一。頭結點不是連結串列的必須要素。
帶有頭結點的指標;
空連結串列:
C語言中用結構指標表示結點:
typedef struct Node { int data; struct Node *next; }Node, *pNode,*LinkList;
其中單鏈表的抽象資料結構即操作有:
void InitList(LinkList *list);//初始化操作,建立空的單鏈表 void ClearList(LinkList *list);//清空單鏈表。 void ListInsert(LinkList *list,int i, int e);//單鏈表第i個位置後面插入變數e void DestoryList(LinkList *list);//銷燬連結串列 bool ListEmpty(LinkList list);//判斷單鏈表是否為空,為空返回真 void GetElem(LinkList, int &e, int i);//將單鏈表中第i個位置的值返回給變數e void ListDelete(LinkList *list, int i, int &e);//刪除單鏈表表第i個位置元素 void ListTraverse(LinkList list);//遍歷線性表 int ListLength(LinkList list);//返回線性表的長度 void Recursion(LinkList list);//遞迴逆序輸出單鏈表
各種函式的實現原始碼:
void InitList(LinkList *list)
{
*list = (LinkList)malloc(sizeof(Node));
(*list)->next = NULL;
(*list)->data = 0;
}
void ListInsert(LinkList *list, int i , int e)//第i個元素後面插入e
{
LinkList p = *list;
if( i == 0)
{
pNode q = (LinkList)malloc(sizeof(Node));
q->next = NULL;
q->data = e;
p->next = q;
}
else
{
pNode p = (*list)->next;
int j = 1;
while( p && i > j)
{
p = p->next;
++j;
}
pNode q = (LinkList)malloc(sizeof(Node));
q->next = p->next;
q->data = e;
p->next = q;
}
}
void ListTraverse(LinkList list)
{
pNode p = list;
if(p != NULL)
{
p = p->next;
}
else
{
return;
}
while(p)
{
printf("%d\t", p->data);
p = p->next;
}
}
void Recursion(LinkList list)//遞迴的方法逆序輸出連結串列
{
if(NULL==list)
{
return;
}
if(list->next!=NULL)
{
Recursion(list->next);
}
printf("%d\t",list->data);
}
bool ListEmpty(LinkList list)
{
pNode p = list;
if(NULL == list->next)
return true;
else
return false;
}
void GetElem(LinkList list, int &e, int i)
{
pNode p = list;
if( i < 0 || i > ListLength(list))
return ;
p = p->next;
int j = 1;
while( j < i)
{
p = p->next;
j++;
}
e = p->data;
}
void ListDelete(LinkList *list, int i, int &e)
{
pNode p = *list;
if( i < 0 || i > ListLength(*list))
return ;
pNode q = p;
p = q->next;
int j = 1;
while( j < i )
{ q = p;
p = p->next;
j++;
}
p->data = e;
q->next = p->next;
free(p);
}
int ListLength(LinkList list)
{
pNode p = list;
int i = 0;
p = p->next;
while(p)
{
p = p->next;
i++;
}
return i;
}
void ClearList (LinkList *list)
{
pNode p = *list;
if( p != NULL)
p = p->next;
pNode q;
while( p )
{
q = p;
p = p->next;
free(q);
}
}
void DestoryList(LinkList *list)
{
pNode p = *list;
if( p != NULL)
p = p->next;
pNode q;
while( p )
{
q = p;
p = p->next;
free(q);
}
free(*list);
}
測試函式原始碼:
int main()
{
LinkList list;
InitList(&list);
ListInsert(&list, 0, 1);
ListInsert(&list, 1, 2);
ListInsert(&list, 2, 3);
ListInsert(&list, 1, 4);
ListInsert(&list, 1, 5);
ListInsert(&list, 5, 6);
ListInsert(&list, 6, 7);
ListInsert(&list, 7, 8);
ListInsert(&list, 8, 9);
ListInsert(&list, 9, 10);
printf("\n遞迴呼叫函式Reversion:\n");
LinkList p = list->next;
Recursion(p);
printf("\n遍歷連結串列ListTranverse:\n");
ListTraverse(list);
int j = ListLength(list);
printf("\n連結串列的長度ListLength:%d\t",j);
int e;
GetElem(list, e, 3);
printf("取連結串列特定的元素GetElem : %d\n",e);
ListDelete(&list, 1, e);
printf("\n刪除連結串列中特定位置的元素:%d\n", e);
ListTraverse(list);
ClearList (&list);
printf("\n連結串列清空ClearList: \n");
ListInsert(&list, 0, 1);
ListInsert(&list, 1, 2);
ListInsert(&list, 2, 3);
ListTraverse(list);
DestoryList(&list);
return 0;
}
參考: 大話資料結構,資料結構(C語言版)嚴蔚敏版