线性表之单链表

什么是线性表?
线性表就是一组数据的集合以某种特定方式排列。该排列方式中除第一个元素和最后一个元素外,每一个元素的前面和后面都有其他元素。第一个元素前面没有其他元素,最后一个元素后面没有其他元素。

线性表在计算机中有不同的存储方式,比如:顺序存储也就是说数据前后的数据在计算机的存储器中是一个一个挨着存的。下面的实现是单链表形式,数据在计算机中的存放位置仅仅是在逻辑上前后挨着,在计算机的存储器里并没有放在一起,数据之间通过指针实现逻辑上的互联。

一个线性表的单链表存储形式的存储形式如图:
单链表
该图中,head指向的为单链表的头结点,该单链表中有两个数据(数据图上未标注 )。
从图中可以看出:

  1. 链表中的每个节点包含一个数据和一个指针(指向下一个节点)。
    链表有一个头节点,不存储元素内容,头节点的指向存储第一个元素的结点。
  2. 线性表为空时,头节点指针项为空(用0表示)。
  3. 线性表不为空时,链表中存储最后一个元素的指针项为空,表示后面没有元素了。
  4. 线性表元素从1开始标号。存储结构中,可以将头结点的编号视为0,实现逻辑编号与物理编号的统一。
  5. head指针指向头结点。

单链表实现:list.h

typedef char EleType;
typedef struct node{
	EleType data;
	struct node * next;
} ChainNode;
typedef struct{
	ChainNode * head;
} List;
List * CreateList(void);
void DestroyList(List *);
void ClearList(List *);
int ListInsert(List *,int,EleType);
int ListDelete(List *,int);
int ListAppend(List *,EleType);
int TraverseList(List *,int (*)(EleType *));
int GetElement(List * l,int n,EleType * data);
ChainNode* NewChainNode(EleType);
ChainNode* GetAddr(List *,int );

List* CreateList(void){
	List * l = 0;
	ChainNode * p = 0;
	EleType * data = 0;
	l = (List *)malloc(sizeof(List));
	if(l == 0) return 0;
	p = NewChainNode(*data);
	if(p==0) return 0;
	l->head = p;
	return l;
}

void DestroyList(List * l){
	ClearList(l);
	free(l->head);
}

void ClearList(List * l){
	while(l->head->next){
		ListDelete(l,1);
	}
}

int ListInsert(List * l,int n,EleType data){
	ChainNode * p = 0;
	ChainNode * newp = 0;
	p = GetAddr(l,n-1);
	if( p == 0 ) return 0;
	newp = NewChainNode(data);
	if(newp == 0 ) return 0;
	newp->next = p->next;
	p->next = newp;
	return 1;
}

int ListDelete(List * l,int n){
	ChainNode * p = 0;
	ChainNode * temp = 0;
	p = GetAddr(l,n-1);
	if(p==0) return 0;
	temp = p->next;
	if(temp==0) return 0;
	p->next = temp->next;
	return 1;
}

int ListAppend(List * l,EleType data){
	ChainNode * p = 0;
	ChainNode * newp = 0;
	p = l->head;
	while(p->next)
		p = p->next;
	newp = NewChainNode(data);
	if(newp == 0 ) return 0;
	p->next = newp;
	return 1;
}

int TraverseList(List * l, int (*f)(EleType  *data)){
	ChainNode * p = 0;
	int cnt = 0;
	EleType * temp =0;
	p = l->head->next;
	while(p){
		cnt++;
		temp = &(p->data);
		if(f(temp) == 0) return cnt;
		p = p->next;
	}
	return -1;
}

int GetElement(List * l,int n,EleType * data){
	ChainNode * p = 0;
	if(n < 1) return 0;
	p = GetAddr(l,n);
	if(p == 0) return 0;
	(*data)=p->data;
	return 1;
}

ChainNode * NewChainNode(EleType data){
	ChainNode * p = 0;
	p = (ChainNode *)malloc(sizeof(ChainNode));
	if(p == 0) return 0;
	p->data = data;
	p->next = 0;
	return p;
}

ChainNode * GetAddr(List * l,int pos){
	ChainNode * p = 0;
	int cnt = 0;
	p = l->head;
	if(pos < 0) return 0;
	while(p && cnt++ < pos){
		p = p->next;
	}
	if(cnt < pos) return 0;
	return p;
}

测试程序如下: m.c

#include"list.h"

#define RIGHT 0
#define WRONG 1
#define CREATELIST 0
#define LISTAPPEND 1
#define LISTINSERT 2
#define LISTDELETE 3
#define GETELEMENT 4
#define CLEARLIST  5
#define titleTest printf("your:");
#define titleSystem printf("\nsyst:");


int putE(EleType*);

void showResult(List*, int no, char *answer);


char* strArr[] =
{

   "---------CreateList Test---------",
   "---------ListAppend Test---------",
   "---------ListInsert Test---------",
   "---------ListDelete Test---------",
   "---------GetElement Test---------",
   "---------ClearList Test---------",   
};


main()
{

     char* arr = "assembly";

     int n = 0;
     List* list;
     char chArr[10] = {0,0,0,0,0,0,0,0,0,0};
     char ch;

     list = CreateList();
     puts(strArr[CREATELIST]);
     if(!list) { puts("createList wrong!"); return; }
     else      { puts("createList no nullpointer!");}
     puts(""); getch();




     for(n=0; arr[n]; n++) ListAppend(list, arr[n]);
     showResult(list, LISTAPPEND, "assembly");


     ListInsert(list,1,'<');
     ListInsert(list,10,'>');
     ListInsert(list,7,'-');
     n = ListInsert(list,0,'0');
     n = n + ListInsert(list,13,'0');
     n = n + ListInsert(list,-1,'0');

     showResult(list, LISTINSERT, "<assem-bly>");
     if(n) puts("insert error!");




     n = 0;     
     ListDelete(list,1);
     ListDelete(list,10);
     ListDelete(list,6);
     ListDelete(list,8);
     ListDelete(list,1);
     ListDelete(list,5);

     n = ListDelete(list,0);
     n = n + ListDelete(list, 6);
     n = n + ListDelete(list, -1);
     showResult(list, LISTDELETE, "sseml");
     if(n) puts("list delete error!");



     n = 0;

     GetElement(list, 5, &ch); chArr[0] = ch;
     GetElement(list, 1, &ch); chArr[1] = ch;
     GetElement(list, 3, &ch); chArr[2] = ch;
     n = GetElement(list, 6, &ch);
     

     puts(strArr[GETELEMENT]);
     titleTest printf("%s",chArr);
     titleSystem puts("lse");
     if(n) puts("getelement error!");
     puts(""); getch();

     ClearList(list);
     showResult(list, CLEARLIST, "");


    
}


void showResult(List* list, int no, char *answer)
{
     puts(strArr[no]);
     titleTest TraverseList(list,putE);  
     titleSystem puts(answer);
     puts(""); getch();

}

int putE(EleType* e)
{
    printf("%c", *e);

    return 1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

记与思

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值