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

数据结构学习一(单链表的操作)

2012-10-23 17:46 621 查看
自己写的一个单链表的例子,注释写的不是特别好,里面可能代码的不是很好。新手入门可以看下。

包括链表的插入、删除、查找、合并、逆序

#include <stdio.h>
#include <stdlib.h>

#define TYPE char
#define FORMAT "%c"
#define CROSSBORDER -1
#define NEGATIVE 100

//链表的一个节点
typedef struct list_node
{
TYPE  value ;
struct list_node * next;
}lnode,*ptrlnode;

//链表
typedef struct list
{
ptrlnode head ;
int length;
}list;

int list_init(list *l)
{
l->length = 0;
l->head = 0 ;
return 0 ;
}

//链表分配失败的输出信息。
void print_memory_fail()
{
printf("Failed to allocate memory!\n");
}

//初始化一个节点,将节点的值设置位,并且将分贝节点的地址返回value 2012-07-30
struct  lnode * list_node(TYPE value )
{
lnode * current  = (lnode *)malloc(sizeof(lnode));
if(NULL == current ) {print_memory_fail();exit(0);}
current->value = value;
current->next = NULL;
return current;
}

//将 value的值查出到链表l的末尾
int list_insert_tail(list *l,TYPE value)
{
ptrlnode tmp,item;
item = l->head;
tmp=(lnode *) malloc(sizeof(lnode));
if(NULL == tmp){printf("Failed to allocate memory!\n");exit(0);};
tmp->value = value;
tmp->next = NULL ;
//检查链表是否为空
if(item)
{
while(item->next)
{
item= item->next;
}
item->next = tmp;l->length++;
}
else
{ l->head = tmp;l->length =1;}
return 0;
}

//l:节点n所在的链表,n:在其后面添加节点了, value:要插入节点值 2012-07-30
int list_insert_node_tail(list * l,ptrlnode n , TYPE value)
{
ptrlnode tmp_node ;
tmp_node = (lnode *)malloc(sizeof(lnode));
if(NULL == tmp_node ){printf("Failed to allocate memeory!\n");exit(0);}
tmp_node ->value = value ;
tmp_node ->next = n->next;
n->next = tmp_node ;
l->length ++;
return 0;
}

//l:节点n所在的链表,n:在其后面添加节点了, value:要插入节点值 2012-07-30
int list_insert_node_location(list * l,lnode *current , unsigned int loc)
{
lnode * pre_node;
int i;
if(0>=loc || l->length < loc)
{
printf("Cross-border!\n");
return CROSSBORDER;
}
else
{
if(1 == loc)
{
current->next=l->head;
l->head =current;
l->length++;
return 0;
}
pre_node = l->head;
for(i=1;i<loc;i++)
{
pre_node = pre_node->next ;
}
current->next = pre_node->next;
pre_node->next = current ;
l->length ++;
}
return 0 ;
}

//在链表l中的current节点后面添加节点insert节点 2012-07-30
int list_insert_node(list *l,lnode * current,lnode * insert)
{
insert ->next = current->next ;
current->next =insert ;
l->length++;
return 0;
}

//在将value的值新建一个节点并且作为链表的头,其余节点后移
int list_insert_head(list *l,TYPE value )
{
ptrlnode tmp_node;
tmp_node=(lnode *) malloc(sizeof(lnode));
if(NULL == tmp_node){printf("Failed to allocate memory!\n");exit(0);};
tmp_node ->value = value ;
l->length++;
tmp_node->next=l->head;
l->head = tmp_node;
return 0 ;
}

//在链表l中的loc新建一个节点并且值为n。其余节点后移(包括本节点)
int list_insert_location(list *l,int loc,TYPE value)
{
ptrlnode tmpnode =NULL;
ptrlnode pre_node=NULL;
int i;
if(0>=loc || l->length < loc)
{
printf("Cross-border!\n");
return CROSSBORDER;
}
else
{
tmpnode = (lnode *) malloc (sizeof(lnode));
if(NULL==tmpnode){printf("Failed to allocate memory!\n");exit(0);}
tmpnode->value = value ;
if(1 == loc)
{tmpnode->next = l->head;l->head=tmpnode;l->length++;return 0;}
pre_node = l->head;
for(i=1;i<loc;i++)
{
pre_node = pre_node->next ;
}
tmpnode->next = pre_node->next;
pre_node->next = tmpnode ;
l->length ++;
}
return 0 ;
}

//查询value值在链表l中出现的次数,返回值value出现的次数,0没有出现,最多出现unsigned int
unsigned int list_find_value_count(list l,TYPE value)
{
int i ,count=0;
for(i=0;i<l.length;i++)
{
if(value == l.head->value)count ++;
l.head = l.head->next;
}
return count;
}

//查询值value在链表l中第一次出现的位,没有出现的值返回0
int list_find_value_first_location(list l,TYPE value)
{
int i;
for(i=0;i<l.length;i++)
{
if(value == l.head->value) return i+1;
l.head = l.head->next;
}
return 0;
}

//查询值value在链表l中第n次出现的位置,如果没有第n次,返回0,有返回位置
int list_find_value_location(list l,unsigned int n,TYPE value)
{
int i,count =0;
for(i=0;l.length;i++)
{
if(value == l.head->value)
{
if(n == ++count)return i+1;
}
}
return 0;
}

//得到链表l中第loc个位置的值,为零时候提示出错,将结果写到result中
int list_get_value(list l,unsigned  int loc,TYPE * result)
{
int i;
if(0==loc) {return CROSSBORDER;}
for(i=0;i<loc-1;i++)
{
l.head = l.head->next;
}
*result = l.head->value;
return 0;
}

//删除链表l中第loc个节点,后面的节点补上。
int list_delete(list *l,int loc)
{
int i;
ptrlnode tmpnode = NULL;
ptrlnode freenode =NULL;
tmpnode = l->head;

if(0>=loc || loc >l->length)
{
printf("cross-border!\n");
return CROSSBORDER;
}
else if(1==loc)
{
freenode =l->head;
l->head = (l->head)->next;
}
else
{

for(i=1;i<loc-1;i++)
{
tmpnode = tmpnode->next;
}
freenode =tmpnode->next;
if(freenode) tmpnode->next =freenode->next; else tmpnode->next = NULL;
}
free(freenode);
l->length --;
return 0;
}

//删除链表l中第一个值是value值的节点 2012-07-30
int list_delete_first(list *l,TYPE value)
{
int i;
ptrlnode tmpnode = NULL;
ptrlnode freenode =NULL;
tmpnode = l->head->next;

if(value  ==  l->head->value)
{ freenode = l->head;l->head = tmpnode;}
else
{
for(i=1;i<l->length-1;i++)
{
tmpnode = tmpnode->next;
}
freenode =tmpnode->next;
if(freenode) tmpnode->next =freenode->next; else tmpnode->next = NULL;
}
free(freenode);
l->length --;
return 0;
}

//打印链表
void list_print(list l)
{
char *str;
char *p;
int i;

if(1 !=sizeof(TYPE))
{
ptrlnode node = l.head;
while(node)
{
printf(FORMAT,node->value );
node = node ->next;
}
}
else
{
str = (char *) malloc(sizeof(char)*l.length);
if(NULL != str)
{
for(i=0;i<l.length;i++)
{
str[i]=l.head->value;
l.head = l.head->next;
}
}
}
printf("%s\n",str);
}

//链表逆转
//原理:源:head -> 1 -> 2 ->3 -> 4 -> null;
//第一步: null <- 1 <- 2 , 3 ->4 - null;
//第二步: null <- 1 <- 2 <- 3, 4 - null;
//第三步: null <- 1 <- 2 <- 3 <- 5;
//最后一步: head -> 5;
void list_reverse(list *l)
{
int length = l->length;
int i;
ptrlnode tmphead = NULL;
ptrlnode node ;
ptrlnode head = l->head;
for(i =0;i<l->length;i++)
{
node = head;
head = head ->next;
node->next = tmphead ;
tmphead = node ;
}
l->head = tmphead ;
}

//将源链表中source拷贝到链表dest中的,但是主要我没有释放dest原有的空间,
//学要保证dest本身为空,source与dest并没有共享空间。
void list_copy(list  source,list * dest)
{
ptrlnode snode = source.head;
ptrlnode dest_node,tmpnode ;
if(snode)
{
dest->head = dest_node=tmpnode = (ptrlnode )malloc(sizeof(lnode));
if(NULL == tmpnode){printf("Failed to allocate memory!\n");exit(0);}
tmpnode->value = snode->value;
snode=snode->next;
while(snode)
{
tmpnode = (ptrlnode )malloc(sizeof(lnode));
if(NULL == tmpnode){printf("Failed to allocate memory!\n");exit(0);}
tmpnode ->value = snode->value ;
dest_node ->next= tmpnode;
dest_node = tmpnode ;
snode = snode ->next;
}
}
dest->length=source.length;
}

//复制链表source中的从start开始的len元素到链表result中,如果len多于剩下的元素,
//复制余下所有的元素
int list_sub(list *source,list *result,int start ,int len)
{
//源链表的节点,用于分配空间的节点,目标链表的前一个节点
ptrlnode source_node,tmp_node,result_previous;
int i;
if(0>=start || start > source->length){printf("start is error \n");return CROSSBORDER;}
if(len >(source->length-start))len = source ->length -start+1;
source_node = source->head;
//找到第一个需要复制的节点
for(i=1;i<start;i++)
{
source_node=source_node->next;
}
//复制节点
result->head=result_previous = tmp_node=(ptrlnode) malloc(sizeof(lnode));
if(NULL == tmp_node){print_memory_fail();exit(0);}
tmp_node->value = source_node->value;
source_node =source_node->next;
for(i=1;i<len;i++)
{

tmp_node=(ptrlnode) malloc(sizeof(ptrlnode));
if(NULL == tmp_node){print_memory_fail();exit(0);}
tmp_node->value = source_node->value;
source_node =source_node->next;
result_previous->next = tmp_node;
result_previous =tmp_node;
}
result->length =len;

return 0;

}

//将链表l的元素合并到链表result后面。
int list_merger_tail(list l,list *result)
{
ptrlnode tmp_node ,result_previous;
int i;
if(0==l.length)return 0;
result_previous = result->head;
for(i=1;i<result->length;i++)
result_previous = result_previous->next;

for(i=0;i<l.length;i++)
{
tmp_node =(ptrlnode)malloc(sizeof(lnode));
if(NULL == tmp_node){print_memory_fail();exit(0);}
tmp_node->value =l.head->value ;
result_previous->next = tmp_node;
result_previous=tmp_node;
l.head = l.head->next;
}
result->length +=l.length;
return 0 ;

}

//销毁链表l,释放空间
void list_destory(list * l)
{
ptrlnode free_node ;
while(l->head)
{
free_node=l->head;
l->head=(l->head)->next;
free(free_node);
}
l->length=0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息