常见的数据结构只有两种:
1、数组
2、链表
数组中的元素是连续存储的,而链表的元素则可以不连续,只需要有指针指向下一个元素即可。因此链表适合存储插入删除比较频繁的一组数据。另外链表的存储空间是动态的,不必预先分配指定的空间大小。。下面介绍链表的几种常见操作。
首先先定义一个链表
struct linklist {
int data;
struct linklist *next;
};
typedef linklist *linklistp;
然后定义两个函数:
/**
头结点插入
*/
linklistp insert_head(linklistp head,linklistp newnode){
newnode->next = head;
head = newnode;
return head;
}
/**
尾结点插入
*/
linklistp insert_tail(linklistp head,linklistp newnode){
if(head == NULL){
head = newnode;
return head;
}
linklistp temp = head;
while (1) {
if(temp->next == NULL){
temp->next = newnode;
break;
}
temp = temp->next;
}
return head;
}
之后我们利用尾节点插入的函数来创建一个链表
linklistp head = NULL;
for(int i = 0;i < 10; i ++){
linklistp newNode = (linklistp)malloc(sizeof(linklist));
newNode->data = i;
newNode->next = NULL;
head = insert_tail(head,newNode);
}
这样就创建了一个包含十个元素的链表。
然后再定义一个函数,求链表长度
/**
获取链表长度
*/
int getLength(linklistp head){
if(head == NULL){
return 0;
}
int count = 1;
linklistp temp = head;
while (temp->next != NULL) {
temp = temp->next;
count ++;
}
return count;
}
然后实现指定位置插入元素的函数
/**
指定位置插入
*/
linklistp insertAtIndex(linklistp head,int index,linklistp newNode){
if(head == NULL){
return head;
}
int length = getLength(head);
//Tips:超出链表范围,直接返回
if(index >= length+1 || index < 0) {
return head;
}
//Tips:如果是在头结点前面插入
if(index == 0){
return insert_head(head, newNode);
}
//Tips:如果是在尾节点后面插入
if(index == length){
return insert_tail(head, newNode);
}
//Tips:先找到要插入位置的前一个元素,并且找到该元素的后继,然后将前一个元素的next指针指向待插入 的元素,待插入的元素的next指针指向刚才我们找到的后继,这样插入操作就完成了
linklistp temp = head;
for(int i = 0; i <= length; i ++){
if(i == index-1){
linklistp nextNode = temp->next;
temp->next = newNode;
newNode->next = nextNode;
break;
}
temp = temp->next;
}
return head;
}
下面再来定义删除指定元素的操作
/**
删除指定节点
*/
linklistp deleteAtIndex(linklistp head,int index){
if(head == NULL){
return head;
}
int length = getLength(head);
if(index < 0 || index > length){
return head;
}
//Tips:如果要删除的是头结点,那么把链表头结点变成原头结点后继,删除原头结点
linklistp temp = head;
if(index == 0){
head = temp->next;
free(temp);
return head;
}
//Tips:删除的时候先找到要删除元素的前一个元素temp,让前一个元素temp的next指向要删除位置的元素 的后继,然后释放被删除的元素
for(int i = 0; i < length; i ++){
if(i == index-1){
linklistp nextNode = temp->next->next;
temp->next = nextNode;
free(temp);
break;
}
temp = temp->next;
}
return head;
}
最后再写一个函数输出链表的所有元素
/**
输出链表元素
*/
void outPut(linklistp head){
linklistp temp = head;
while (temp) {
printf("%d\n",temp->data);
temp = temp->next;
}
}
这样就可以进行操作删除的验证了