C 有頭結點連結串列的若干操作
阿新 • • 發佈:2018-11-01
比無頭節點的要簡單很多
文章目錄
- 建立
- 輸出
- 訪問第i個元素
- 在i個位置前插入
- 刪除第i個元素
- 頭插
- 逆置
- 尾插
- 排序
- 兩個有序連結串列合併在一起,合併在一起的連結串列也要有序
- 找出連結串列中資料最大的節點並返回
- 連結串列中最小的節點放在最前面
- 有序連結串列中去除相同值的節點
- 升序表裡比x小的有幾個
建立
typedef struct Node {
int data;
struct Node * next;
} LNode, * LinkNode;
//建立,絲毫不用理會第一個節點特殊情況
void creatLink(LinkNode * q){
int i;
LinkNode e, p1;
//頭節點
*q = (LinkNode)malloc(sizeof(LNode));
(*q)->next = NULL;
p1 = *q;
for (i = 0; i < 10; i++) {
//建立新節點
e = (LinkNode)malloc(sizeof(LNode));
e->data = i+1;
e-> next = NULL;
//把新節點接在連結串列中
p1->next = e;
p1 = e;
}
}
輸出
//輸出,讓過第一個頭節點
void putout(LinkNode q){
LinkNode p1 = q->next;
while (p1) {
printf("%d ", p1->data);
p1 = p1->next;
}
printf("\n");
}
訪問第i個元素
/*訪問第i個元素,並且返回,以引數的方式返回了,這個就是C語言的侷限了,
只能返回一個引數,不像別的能返回個元組什麼的*/
Status findElement(LinkNode q, int i, int *e){
if(i < 1) return ERR;
LinkNode p1 = q->next;
//很實在從1開始
int n = 1;
while (p1) {
//這個就是第幾個了
if(n == i) {
*e = p1->data;
return OK;
}
p1 = p1->next;
n++;
}
return ERR;
}
在i個位置前插入
Status insertElement(LinkNode q, int i, int e){
if(i < 1 || !q) return ERR;
//前驅p2,後繼p1
LinkNode p1 = q->next, p2 = q;
int n = 1;
while (p1) {
//還是先找到第i個位置,以及在第i個位置上的元素和其前驅元素
if(n == i){
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
element->next = NULL;
//插入元素
p2->next = element;
element->next = p1;
return OK;
}
n++;
p2 = p1;
p1 = p1->next;
}
return ERR;
}
刪除第i個元素
//刪除第i個元素
Status deleteElement(LinkNode *q, int i, int *e){
if(i < 1 || !((*q)->next)) return ERR;
//還是前驅後繼
LinkNode p1 = (*q)->next, p2 = (*q);
int n = 1;
while (p1) {
//找到第i個元素
if(n == i)
{
(*e) = p1->data;
p2->next = p1->next;
free(p1);
return OK;
}
n++;
p2 = p1;
p1 = p1->next;
}
return ERR;
}
頭插
//頭插
Status inserthead(LinkNode *q, int e) {
if(!(*q)) return ERR;
LinkNode p1 = *q;
//從頭開始
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
element->next = p1->next;
p1->next = element;
return OK;
}
逆置
//逆置
void reverse(LinkNode *q){
//將頭節點獨立出來,慣例找前驅後繼
LinkNode p1, p2;
p1 = (*q)->next;
(*q)->next = NULL;
//將元素一次取出來,再按著頭插法,插進去
while (p1) {
p2 = p1;
p1 = p1->next;
//每次取出來的元素都插在最前面
p2->next = (*q)->next;
(*q)->next = p2;
}
}
尾插
//尾插
Status inserttail(LinkNode *q, int e) {
if(!(*q)) return ERR;
LinkNode p1 = *q;
//p1就是最後一個節點
while (p1->next) {
p1 = p1->next;
}
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
element->next = NULL;
//接上
p1->next = element;
return OK;
}
排序
//排序
void sort(LinkNode *q){
LinkNode p1, p2;
int temp;
p1 = p2 = (*q)->next;
//選擇
// for (; p1->next; p1 = p1->next) {
// for (p2 = p1->next; p2; p2 = p2->next) {
// if(p1->data > p2->data){
// temp = p2->data;
// p2->data = p1->data;
// p1->data = temp;
// }
// }
// }
//冒泡 每趟只能遍歷到最後,有些許浪費
for (; p1->next; p1 = p1->next) {
for (p2 = (*q)->next; p2->next; p2 = p2->next) {
if(p2->data > p2->next->data){
temp = p2->data;
p2->data = p2->next->data;
p2->next->data = temp;
}
}
}
}
兩個有序連結串列合併在一起,合併在一起的連結串列也要有序
//la和lb遞增,歸併起來lc
LinkNode combine2Links(LinkNode *q1, LinkNode *q2){
//LinkNode =(* LNode)就是一個指標
//把兩個連結串列的第一個有數字的結點取出來,
LinkNode p1 = (*q1)->next;
LinkNode p2 = (*q2)->next;
//我現在認為連結串列1就是合併成新的連結串列
LinkNode L = *q1;
//第二個連結串列的頭結點於我來說莫得用了
free(*q2);
//遍歷p1和p2,哪個小先放哪個
while (p1 && p2) {
if(p2->data > p1->data){
L->next = p1;
p1 = p1->next;
}else{
L->next = p2;
p2 = p2->next;
}
L = L->next;
}
//最後剩下哪個全接上去
if(p2){
L->next = p2;
}
if(p1){
L->next = p1;
}
//返回連結串列1
return *(q1);
}
找出連結串列中資料最大的節點並返回
LinkNode findmax(LinkNode q){
LinkNode p1 = q->next, max = NULL;
//記錄值
int m = 0;
while (p1) {
//只要發現比它大的,記錄節點也重新整理值
if(m < p1->data){
m = p1->data;
max = p1;
}
//往後走
p1 = p1->next;
}
return max;
}
連結串列中最小的節點放在最前面
//將連結串列最小節點移動到連結串列最前面
void insertMinNode(LinkNode *head){
//遍歷的時候前驅後繼
LinkNode p1 = (*head)->next;
LinkNode p = (*head);
//最小點的前驅後繼
LinkNode minPreNode = NULL, minNode = NULL;
//初值
int min = p1->data;
//動起來
while (p1) {
//只要發現還有小的就更新節點
if(min > p1->data){
min = p1->data;
minNode = p1;
minPreNode = p;
}
//驅動著往後走
p = p1;
p1 = p1->next;
}
//遍歷完一次,留下的就是我們要的了,ps.連結串列中最好不要出現兩個一樣小的
//刪除原有的位置
minPreNode->next = minNode->next;
//新增到新的地方
minNode->next = (*head)->next;
(*head)->next = minNode;
}
有序連結串列中去除相同值的節點
//有序連結串列中去除相同值的節點
void deleteSimilarNode(LinkNode *head){
//前驅後繼
LinkNode prenode = (*head)->next;
LinkNode node = prenode->next;
//往下走
while (node) {
//要是相等就走後面的,前頭等著直到走完
if(prenode->data == node->data){
prenode->next = node->next;
free(node);
node = prenode->next;
}
else
//既然不相等,就都往後移動
{
prenode = node;
node = node->next;
}
}
}
升序表裡比x小的有幾個
//升序表裡比x小的有幾個
int lessThanNode(LinkNode q, int x){
LinkNode p1 = q->next;
int n = 0;
while (p1) {
//升序,碰見比x大的,那後面肯定都是大的,跳出
if(p1->data >= x)
break;
n++;
p1 = p1->next;
}
return n;
}
//
// main.c
// 單鏈表有頭結點
//
// Created by 赫凱 on 2018/10/23.
// Copyright © 2018年 赫凱. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERR 0
#define num 0
typedef int Status;
typedef struct Node {
int data;
struct Node * next;
} LNode, * LinkNode;
//建立,絲毫不用理會第一個節點特殊情況
void creatLink(LinkNode * q){
int i;
LinkNode e, p1;
*q = (LinkNode)malloc(sizeof(LNode));
(*q)->next = NULL;
p1 = *q;
for (i = 0; i < num; i++) {
e = (LinkNode)malloc(sizeof(LNode));
e->data = i+1;
e->next = NULL;
p1->next = e;
p1 = e;
}
}
//輸出,讓過第一個頭節點
void putout(LinkNode q){
LinkNode p1 = q->next;
while (p1) {
printf("%d ", p1->data);
p1 = p1->next;
}
printf("\n");
}
//訪問第i個元素
Status findElement(LinkNode q, int i, int *e){
if(i < 1) return ERR;
LinkNode p1 = q->next;
int n = 1;
while (p1) {
if(n == i) {
*e = p1->data;
return OK;
}
p1 = p1->next;
n++;
}
return ERR;
}
//在i個位置前插入
Status insertElement(LinkNode q, int i, int e){
if(i < 1 || !q) return ERR;
LinkNode p1 = q->next, p2 = q;
int n = 1;
while (p1) {
if(n == i){
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
element->next = NULL;
p2->next = element;
element->next = p1;
return OK;
}
n++;
p2 = p1;
p1 = p1->next;
}
return ERR;
}
//刪除第i個元素
Status deleteElement(LinkNode *q, int i, int *e){
if(i < 1 || !((*q)->next)) return ERR;
LinkNode p1 = (*q)->next, p2 = (*q);
int n = 1;
while (p1) {
if(n == i)
{
(*e) = p1->data;
p2->next = p1->next;
free(p1);
return OK;
}
n++;
p2 = p1;
p1 = p1->next;
}
return ERR;
}
//頭插
Status inserthead(LinkNode *q, int e) {
if(!(*q)) return ERR;
LinkNode p1 = *q;
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
element->next = p1->next;
p1->next = element;
return OK;
}
//尾插
Status inserttail(LinkNode *q, int e) {
if(!(*q)) return ERR;
LinkNode p1 = *q;
while (p1->next) {
p1 = p1->next;
}
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
p1->next = element;
element->next = NULL;
return OK;
}
int main(int argc, const char * argv[]) {
// insert code here...
printf("Hello, World!\n");
int e, i;
LinkNode head = NULL;
//建立
creatLink(&head);
putout(head);
//頭插尾插
for (i = 0; i < 10; i+=2) {
if(!inserthead(&head, i)) printf("頭插失敗");
if(!inserttail(&head, i)) printf("尾插失敗");
}
putout(head);
//查詢
printf("\n查詢\n");
scanf("%d", &i);
while (i) {
if(findElement(head, i, &e)){
printf("第 %d 位置上為 %d\n", i, e);
}else{
printf("輸入引數錯誤!!!\n");
}
scanf("%