您的位置:首页 > 理论基础 > 数据结构算法

(2)数据结构——线性表(链表)实现

2013-08-06 15:10 423 查看
带头结点的单链表实现

LinkList.h

/*********************************************************************
*:
*:            Author: dspeeding
*:          Copyright (c) 2013, dspeeding
*:
*:        Created at: 2013.08.06
*:     Last modified: 2013.08.06
*:
*:      Introduction: 线性表链式实现
*:
*:    注:ElemType类型 不能进行深拷贝,请留意
*:  如使用 TraverseList 函数 则需要自己实现Visit函数
*:    如使用 SortList 函数 则需要自己实现Compare函数
*:    SortList 使用简单冒泡排序算法实现
*:
*:*********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//定义数据类型为int型
typedef int ElemType;

typedef struct LNode{
ElemType data;        //数据
struct LNode *next;    //下一指针
}LNode;

typedef LNode* LinkList;
typedef LinkList* PLinkList;

//定义数据类型的打印函数
typedef void (*Visit)(ElemType*);

//定义数据类型的比较函数
typedef int (*Compare)(ElemType*, ElemType*);

/****************************************
Purpose :     初始化线性表
Input   :     L            -- 线性表指针
Return  :     0            --OK
-1            --FAIL
*****************************************/
int InitList(PLinkList L);

/****************************************
Purpose :     清空链表
Input   :     L            -- 线性表指针
Return  :     None
*****************************************/
void ClearList(PLinkList L);

/****************************************
Purpose :     线性表长度
Input   :     L            -- 线性表指针
Return  :     线性表长度   如果是-1,则表示出错
*****************************************/
int ListLength(PLinkList L);

/****************************************
Purpose :     取链表中第nPos个元素
Input   :     L            -- 线性表指针
nPos        -- 位置
val            -- 要取到的元素
Return  :     0            --OK
-1            --FAIL
*****************************************/
int GetElem(PLinkList L, int nPos, ElemType *val);

/****************************************
Purpose :     在线性表中第nPos个位置插入新元素
Input   :     L            -- 线性表指针
nPos        -- 位置[1,ListLength(L)+1]
val            -- 要插入的元素
Return  :     0            --OK
-1            --FAIL
*****************************************/
int InsertList(PLinkList L, int nPos, ElemType *val);

/****************************************
Purpose :     在线性表中第nPos个位置删除元素
Input   :     L            -- 线性表指针
nPos        -- 位置[1,ListLength(L)]
val            -- 数据
Return  :     0            --OK
-1            --FAIL
*****************************************/
int DeleteList(PLinkList L, int nPos, ElemType *val);

/****************************************
Purpose :     返回线性表中第一个与e相等的数据元素的位序
Input   :     L            -- 线性表指针
val            -- 数据
compare        -- 比较函数的函数指针
Return  :     索引值,如果没有找到则返回-1
*****************************************/
int LocateElem(PLinkList L, ElemType *val, Compare compare);

/****************************************
Purpose :     遍历输出线性表中每个元素
Input   :     L            -- 线性表指针
visit        -- 遍历函数指针
Return  :     None
*****************************************/
void TraverseList(PLinkList L, Visit visit);

/****************************************
Purpose :     更新第nPos个位置元素
Input   :     L            -- 线性表指针
nPos        -- 元素的位置  [1, ListLength[L]]
data        -- 要更新的元素
Return  :     0            --OK
-1            --FAIL
*****************************************/
int UpdateList(PLinkList L, int nPos, ElemType* val);

/****************************************
Purpose :     对线性表进行排序
Input   :     L            -- 线性表指针
compare        -- 比较函数
Return  :     0            --OK
-1            --FAIL
*****************************************/
int SortList(PLinkList L, Compare compare);

/****************************************
Purpose :     对线性表进行逆置
Input   :     L            -- 线性表指针
compare        -- 比较函数
Return  :     0            --OK
-1            --FAIL
*****************************************/
int ReverseList(PLinkList L);


LinkList.c

#include "LinkList.h"

/****************************************
Purpose :     初始化线性表
Input   :     L            -- 线性表指针
Return  :     0            --OK
-1            --FAIL
*****************************************/
int InitList(PLinkList L)
{
//带头结点的单链表
*L = (LinkList)malloc(sizeof(LNode));
if(!*L)
{
return -1;
}
(*L)->next = NULL;
return 0;
}

/****************************************
Purpose :     清空链表
Input   :     L            -- 线性表指针
Return  :     None
*****************************************/
void ClearList(PLinkList L)
{
LinkList p = *L;
while((*L)->next)
{
p=p->next;
free(*L);
*L = p;
}
(*L)->next = NULL;
}

/****************************************
Purpose :     线性表长度
Input   :     L            -- 线性表指针
Return  :     线性表长度   如果是-1,则表示出错
*****************************************/
int ListLength(PLinkList L)
{
LinkList p = NULL;
int nLen = 0;
if(*L == NULL)
{
return -1;
}
p = (*L)->next;
while(p)
{
p = p->next;
nLen++;
}
return nLen;
}

/****************************************
Purpose :     取链表中第nPos个元素
Input   :     L            -- 线性表指针
nPos        -- 位置
val            -- 要取到的元素
Return  :     0            --OK
-1            --FAIL
*****************************************/
int GetElem(PLinkList L, int nPos, ElemType *val)
{
LinkList p = *L;
int i = 0;
if(nPos > ListLength(L) || nPos < 0)
{
return -1;
}
while(i < nPos && p)
{
p = p->next;
i++;
}
memcpy(val, &p->data, sizeof(ElemType));
return 0;
}

/****************************************
Purpose :     在线性表中第nPos个位置插入新元素
Input   :     L            -- 线性表指针
nPos        -- 位置  [1,ListLength(L)+1]
val            -- 要插入的元素
Return  :     0            --OK
-1            --FAIL
*****************************************/
int InsertList(PLinkList L, int nPos, ElemType *val)
{
LinkList p = *L;
LinkList q = NULL;
int i = 0;
int nLen = ListLength(L);
if(nPos < 1|| nPos > nLen+1)
{
return -1;
}
q = (LinkList)malloc(sizeof(LNode));
if(q == NULL)
{
return -1;
}
while(i < nPos - 1)
{
p = p->next;
i++;
}

memcpy(&q->data, val, sizeof(ElemType));
q->next = p->next;
p->next = q;
return 0;
}

/****************************************
Purpose :     在线性表中第nPos个位置删除元素
Input   :     L            -- 线性表指针
nPos        -- 位置[1,ListLength(L)]
val            -- 数据
Return  :     0            --OK
-1            --FAIL
*****************************************/
int DeleteList(PLinkList L, int nPos, ElemType *val)
{
LinkList p = *L;
LinkList q = NULL;
int i;
if(nPos < 1 || nPos > ListLength(L))
{
return -1;
}
while(i < nPos -1)
{
p = p->next;
i++;
}
q = p->next;
p->next = q->next;
memcpy(val, &q->data, sizeof(ElemType));
free(q);
q = NULL;
return 0;
}

/****************************************
Purpose :     返回线性表中第一个与e相等的数据元素的位序
Input   :     L            -- 线性表指针
val            -- 数据
compare        -- 比较函数的函数指针
Return  :     索引值,如果没有找到则返回-1
*****************************************/
int LocateElem(LinkList *L, ElemType *val, Compare compare)
{
LinkList p = NULL;
int i = 1;
if(*L == NULL)
{
return -1;
}
p = (*L)->next;
while(p && compare(val, &p->data) != 0)
{
p = p->next;
i++;
}
if(p == NULL)
{
return -1;
}
return i;
}

/****************************************
Purpose :     遍历输出线性表中每个元素
Input   :     L            -- 线性表指针
visit        -- 遍历函数指针
Return  :     None
*****************************************/
void TraverseList(PLinkList L, Visit visit)
{
LinkList p = NULL;
if(*L != NULL)
{
p = (*L)->next;
while(p != NULL)
{
visit(&p->data);
p = p->next;
}
}
}

/****************************************
Purpose :     更新第nPos个位置元素
Input   :     L            -- 线性表指针
nPos        -- 元素的位置  [1, ListLength[L]]
data        -- 要更新的元素
Return  :     0            --OK
-1            --FAIL
*****************************************/
int UpdateList(PLinkList L, int nPos, ElemType* val)
{
int i = 0;
LinkList p = NULL;
if(nPos < 1 && nPos > ListLength(L))
{
return -1;
}
p = *L;
while(i < nPos)
{
p = p->next;
i++;
}

memcpy(&p->data, val, sizeof(ElemType));
return 0;
}

/****************************************
Purpose :     对线性表进行排序
Input   :     L            -- 线性表指针
compare        -- 比较函数
Return  :     0            --OK
-1            --FAIL
*****************************************/
int SortList(PLinkList L, Compare compare)
{
LinkList p = NULL;
LinkList q = NULL;
ElemType tmp;
if(*L == NULL)
{
return -1;
}
for(p = (*L)->next;p!=NULL;p=p->next)
{
for(q=p->next;q!=NULL;q=q->next)
{
if(compare(&q->data, &p->data) < 0)
{
memcpy(&tmp, &q->data, sizeof(ElemType));
memcpy(&q->data, &p->data, sizeof(ElemType));
memcpy(&p->data, &tmp, sizeof(ElemType));
}
}
}
return 0;
}

/****************************************
Purpose :     对线性表进行逆置
Input   :     L            -- 线性表指针
compare        -- 比较函数
Return  :     0            --OK
-1            --FAIL
*****************************************/
int ReverseList(PLinkList L)
{
LinkList p = NULL;
LinkList q = NULL;
LinkList s = NULL;
if(*L == NULL)
{
return -1;
}
p = (*L)->next;
if(p == NULL)
{
//没有数据则返回正确
return 0;
}
q = p->next;
while(q->next != NULL)
{
s = q->next;
q->next = p;
p = q;
q = s;
}
q->next = p;                //最后一个节点的next调整下
(*L)->next->next = NULL;    //保留头结点
(*L)->next = q;
return 0;
}


testmain.c

#include <stdio.h>
#include "LinkList.h"

void visit(ElemType *val)
{
printf("%3d  ", *val);
}
int compare(ElemType* e1, ElemType* e2)
{
return *e1 - *e2;
}
int main(int argc, char* argv[])
{
LinkList L;
int i;
ElemType val;
printf("初始化线性表\n");
if(InitList(&L))
{
printf("初始化线性表失败\n");
return -1;
}
printf("插入数据1\n");
val  = 3;
if(InsertList(&L, 1, &val))
{
printf("插入线性表数据失败\n");
}
printf("插入数据2\n");
val  = 200;
if(InsertList(&L, 1, &val))
{
printf("插入线性表数据失败\n");
}
val  = -1;
if(InsertList(&L, 1, &val))
{
printf("插入线性表数据失败\n");
}
for(i=0;i<8;i++)
{
val = i;
if(InsertList(&L, 1, &val))
{
printf("插入线性表数据失败\n");
}
}
TraverseList(&L, visit);
/*val  = 555;
if(InsertList(&L, ListLength(&L), &val))
{
printf("插入线性表数据失败\n");
}
TraverseList(&L, visit);
printf("排序数据\n");
SortList(&L, compare);
TraverseList(&L, visit);
printf("获取数据\n");
if(GetElem(&L, 1, &val))
{
printf("获取数据失败\n");
}
visit(&val);*/
/*int nLen = ListLength(&L);
printf("线性表长度[%d]\n", nLen);
printf("删除数据\n");
if(DeleteList(&L, nLen, &val))
{
printf("删除数据失败\n");
}
TraverseList(&L, visit);
printf("删除的数据为\n");
visit(&val);
printf("更新数据\n");
val = 1000;
if(UpdateList(&L, 2, &val))
{
printf("更新数据失败\n");
}
TraverseList(&L, visit);

val = 555;
int nIndex = LocateElem(&L, &val, compare);
printf("定位数据位置为[%d]\n", nIndex);
*/
printf("\n逆置链表\n");
if(ReverseList(&L))
{
printf("逆置失败\n");
}
TraverseList(&L, visit);
printf("\n");
ClearList(&L);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: